From 7372d94b700a0167a4045f9b9ae8a9e290ea1581 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Thu, 25 Jul 2024 18:26:06 +0100 Subject: [PATCH 001/125] chore: include liquidity provider in legs --- packages/sushi/src/router/makeAPI02Object.ts | 10 +++++++--- packages/sushi/src/router/router.ts | 4 +++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/sushi/src/router/makeAPI02Object.ts b/packages/sushi/src/router/makeAPI02Object.ts index 9d6ace3d0d..b3faafb21c 100644 --- a/packages/sushi/src/router/makeAPI02Object.ts +++ b/packages/sushi/src/router/makeAPI02Object.ts @@ -1,4 +1,5 @@ import { MultiRoute, RToken, RouteLeg, RouteStatus } from '../tines/index.js' +import { LiquidityProviders } from './liquidity-providers/LiquidityProvider.js' import { RPParams } from './router.js' function makeAPI02Token(token: RToken) { @@ -10,13 +11,16 @@ function makeAPI02Token(token: RToken) { } } -function makeAPI02Leg(leg: RouteLeg, tokens: TokenConvertor) { +function makeAPI02Leg( + leg: RouteLeg & { poolName: string; liquidityProvider: LiquidityProviders }, + tokens: TokenConvertor, +) { return { poolAddress: leg.poolAddress, poolType: leg.poolType, - // @ts-ignore - poolName: leg.poolName as string, // Don't know how, but it exists. Too long to recreate it from poolCodes + poolName: leg.poolName, // Don't know how, but it exists. Too long to recreate it from poolCodes poolFee: leg.poolFee, + liquidityProvider: leg.liquidityProvider, tokenFrom: tokens.getTokenIndex(leg.tokenFrom), tokenTo: tokens.getTokenIndex(leg.tokenTo), share: leg.absolutePortion, diff --git a/packages/sushi/src/router/router.ts b/packages/sushi/src/router/router.ts index d79c79c03f..bd86b0fed0 100644 --- a/packages/sushi/src/router/router.ts +++ b/packages/sushi/src/router/router.ts @@ -211,7 +211,9 @@ export class Router { ...route, legs: route.legs.map((l) => ({ ...l, - poolName: poolCodesMap.get(l.poolAddress)?.poolName ?? 'Unknown Pool', + liquidityProvider: + poolCodesMap.get(l.uniqueId)?.poolName ?? 'Unknown LiquidityProvider', + poolName: poolCodesMap.get(l.uniqueId)?.poolName ?? 'Unknown Pool', })), } } From f73cbce212ddbbb9d8a3c5d89b330256a617582b Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Thu, 25 Jul 2024 18:54:06 +0100 Subject: [PATCH 002/125] fix: compilation --- packages/sushi/src/router/makeAPI02Object.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/sushi/src/router/makeAPI02Object.ts b/packages/sushi/src/router/makeAPI02Object.ts index b3faafb21c..2f814de832 100644 --- a/packages/sushi/src/router/makeAPI02Object.ts +++ b/packages/sushi/src/router/makeAPI02Object.ts @@ -11,15 +11,14 @@ function makeAPI02Token(token: RToken) { } } -function makeAPI02Leg( - leg: RouteLeg & { poolName: string; liquidityProvider: LiquidityProviders }, - tokens: TokenConvertor, -) { +function makeAPI02Leg(leg: RouteLeg, tokens: TokenConvertor) { return { poolAddress: leg.poolAddress, poolType: leg.poolType, + // @ts-ignore poolName: leg.poolName, // Don't know how, but it exists. Too long to recreate it from poolCodes poolFee: leg.poolFee, + // @ts-ignore liquidityProvider: leg.liquidityProvider, tokenFrom: tokens.getTokenIndex(leg.tokenFrom), tokenTo: tokens.getTokenIndex(leg.tokenTo), From 3e29bb89250f3740cc14b6f2dc6a87c8ce93ff57 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Thu, 25 Jul 2024 18:57:34 +0100 Subject: [PATCH 003/125] fix: type --- packages/sushi/src/router/makeAPI02Object.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/sushi/src/router/makeAPI02Object.ts b/packages/sushi/src/router/makeAPI02Object.ts index 2f814de832..7ec0d503f4 100644 --- a/packages/sushi/src/router/makeAPI02Object.ts +++ b/packages/sushi/src/router/makeAPI02Object.ts @@ -16,10 +16,10 @@ function makeAPI02Leg(leg: RouteLeg, tokens: TokenConvertor) { poolAddress: leg.poolAddress, poolType: leg.poolType, // @ts-ignore - poolName: leg.poolName, // Don't know how, but it exists. Too long to recreate it from poolCodes + poolName: leg.poolName as string, // Don't know how, but it exists. Too long to recreate it from poolCodes poolFee: leg.poolFee, // @ts-ignore - liquidityProvider: leg.liquidityProvider, + liquidityProvider: leg.liquidityProvider as LiquidityProviders, tokenFrom: tokens.getTokenIndex(leg.tokenFrom), tokenTo: tokens.getTokenIndex(leg.tokenTo), share: leg.absolutePortion, From ee0fe525f3a618aebbae958b8abcab0d6ec5dcdb Mon Sep 17 00:00:00 2001 From: 0xMasayoshi <0xMasayoshi@protonmail.com> Date: Fri, 26 Jul 2024 03:53:44 +0700 Subject: [PATCH 004/125] chore: update extractor config w/ uni v3 --- apis/extractor/src/config.ts | 12 ++++++++++-- packages/sushi/src/config/uniswap-v3.ts | 7 +++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/apis/extractor/src/config.ts b/apis/extractor/src/config.ts index f49ac086e3..f368f61c27 100644 --- a/apis/extractor/src/config.ts +++ b/apis/extractor/src/config.ts @@ -515,7 +515,10 @@ export const EXTRACTOR_CONFIG: Record< [ChainId.SCROLL]: { client: createPublicClient(extractorClientConfig(ChainId.SCROLL)), factoriesV2: [sushiswapV2Factory(ChainId.SCROLL)], - factoriesV3: [sushiswapV3Factory(ChainId.SCROLL)], + factoriesV3: [ + sushiswapV3Factory(ChainId.SCROLL), + uniswapV3Factory(ChainId.SCROLL), + ], tickHelperContractV3: SUSHISWAP_V3_TICK_LENS[ChainId.SCROLL], tickHelperContractAlgebra: '0x0000000000000000000000000000000000000000' as Address, @@ -529,6 +532,7 @@ export const EXTRACTOR_CONFIG: Record< factoriesV3: [ sushiswapV3Factory(ChainId.LINEA), pancakeswapV3Factory(ChainId.LINEA), + uniswapV3Factory(ChainId.LINEA), ], tickHelperContractV3: SUSHISWAP_V3_TICK_LENS[ChainId.LINEA], tickHelperContractAlgebra: @@ -540,7 +544,10 @@ export const EXTRACTOR_CONFIG: Record< [ChainId.FILECOIN]: { client: createPublicClient(extractorClientConfig(ChainId.FILECOIN)), factoriesV2: [sushiswapV2Factory(ChainId.FILECOIN)], - factoriesV3: [sushiswapV3Factory(ChainId.FILECOIN)], + factoriesV3: [ + sushiswapV3Factory(ChainId.FILECOIN), + uniswapV3Factory(ChainId.FILECOIN), + ], tickHelperContractV3: SUSHISWAP_V3_TICK_LENS[ChainId.FILECOIN], tickHelperContractAlgebra: '0x0000000000000000000000000000000000000000' as Address, @@ -766,6 +773,7 @@ export const EXTRACTOR_CONFIG: Record< ], factoriesV3: [ sushiswapV3Factory(ChainId.BLAST), + uniswapV3Factory(ChainId.BLAST), { address: '0x48d0F09710794313f33619c95147F34458BF7C3b', provider: LiquidityProviders.MonoswapV3, diff --git a/packages/sushi/src/config/uniswap-v3.ts b/packages/sushi/src/config/uniswap-v3.ts index 1870a359d5..a5cd27f614 100644 --- a/packages/sushi/src/config/uniswap-v3.ts +++ b/packages/sushi/src/config/uniswap-v3.ts @@ -46,6 +46,8 @@ export const UNISWAP_V3_SUPPORTED_CHAIN_IDS = [ ChainId.FILECOIN, ChainId.MOONBEAM, ChainId.LINEA, + ChainId.BLAST, + ChainId.ZKSYNC_ERA, ] as const export const UniswapV3ChainIds = UNISWAP_V3_SUPPORTED_CHAIN_IDS @@ -76,6 +78,9 @@ export const UNISWAP_V3_INIT_CODE_HASH: Record< [ChainId.BOBA]: POOL_INIT_CODE_HASH, [ChainId.MOONBEAM]: POOL_INIT_CODE_HASH, [ChainId.LINEA]: POOL_INIT_CODE_HASH, + [ChainId.BLAST]: POOL_INIT_CODE_HASH, + [ChainId.ZKSYNC_ERA]: + '0x010013f177ea1fcbc4520f9a3ca7cd2d1d77959e05aa66484027cb38e712aeed', } as const export const UNISWAP_V3_FACTORY_ADDRESS: Record< @@ -97,4 +102,6 @@ export const UNISWAP_V3_FACTORY_ADDRESS: Record< [ChainId.BOBA]: '0xFFCd7Aed9C627E82A765c3247d562239507f6f1B', [ChainId.MOONBEAM]: '0x28f1158795A3585CaAA3cD6469CD65382b89BB70', [ChainId.LINEA]: '0x31FAfd4889FA1269F7a13A66eE0fB458f27D72A9', + [ChainId.BLAST]: '0x792edAdE80af5fC680d96a2eD80A44247D2Cf6Fd', + [ChainId.ZKSYNC_ERA]: '0x8FdA5a7a8dCA67BBcDd10F02Fa0649A937215422', } as const From bfa07349bc762a8c133565fd406bc1863f9251a0 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Thu, 25 Jul 2024 23:35:08 +0100 Subject: [PATCH 005/125] fix: liquidity provider --- packages/sushi/src/router/router.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/sushi/src/router/router.ts b/packages/sushi/src/router/router.ts index bd86b0fed0..9ac36be6af 100644 --- a/packages/sushi/src/router/router.ts +++ b/packages/sushi/src/router/router.ts @@ -212,7 +212,8 @@ export class Router { legs: route.legs.map((l) => ({ ...l, liquidityProvider: - poolCodesMap.get(l.uniqueId)?.poolName ?? 'Unknown LiquidityProvider', + poolCodesMap.get(l.uniqueId)?.liquidityProvider ?? + 'Unknown Liquidity Provider', poolName: poolCodesMap.get(l.uniqueId)?.poolName ?? 'Unknown Pool', })), } From e3aaed7b755aca8fa3a14ba1d941ffd780e18280 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Wed, 24 Jul 2024 09:50:25 +0100 Subject: [PATCH 006/125] savepoint --- apis/router/.env.example | 7 + apis/router/src/handlers/swap2/index.ts | 120 ++++++++-------- apis/router/src/handlers/swap2/schema.ts | 43 ++++-- apps/web/next.config.mjs | 10 ++ apps/web/src/app/(non-evm)/aptos/layout.tsx | 2 +- apps/web/src/app/(non-evm)/test/layout.tsx | 16 +++ apps/web/src/app/(non-evm)/test/page.tsx | 5 + apps/web/src/app/(non-evm)/test/swap/page.tsx | 5 + apps/web/src/app/(non-evm)/tron/layout.tsx | 9 ++ apps/web/src/app/(non-evm)/tron/page.tsx | 10 ++ k8s/chart/values.yaml | 128 +++++++++--------- packages/sushi/src/router/makeAPI02Object.ts | 100 +++++++++++++- packages/sushi/src/router/router.ts | 2 +- .../sushi/src/serializer/AddressValidation.ts | 4 +- 14 files changed, 316 insertions(+), 145 deletions(-) create mode 100644 apis/router/.env.example create mode 100644 apps/web/src/app/(non-evm)/test/layout.tsx create mode 100644 apps/web/src/app/(non-evm)/test/page.tsx create mode 100644 apps/web/src/app/(non-evm)/test/swap/page.tsx create mode 100644 apps/web/src/app/(non-evm)/tron/layout.tsx create mode 100644 apps/web/src/app/(non-evm)/tron/page.tsx diff --git a/apis/router/.env.example b/apis/router/.env.example new file mode 100644 index 0000000000..80f506e422 --- /dev/null +++ b/apis/router/.env.example @@ -0,0 +1,7 @@ +CHAIN_ID=1 +DRPC_ID= +ALCHEMY_ID= +PORT=3000 +SENTRY_DSN= +SENTRY_ENVIRONMENT=local +EXTRACTOR_SERVER=http://localhost:3000 \ No newline at end of file diff --git a/apis/router/src/handlers/swap2/index.ts b/apis/router/src/handlers/swap2/index.ts index 02e90170de..79ae99723b 100644 --- a/apis/router/src/handlers/swap2/index.ts +++ b/apis/router/src/handlers/swap2/index.ts @@ -1,17 +1,18 @@ import { Logger, safeSerialize } from '@sushiswap/extractor' import { Request, Response } from 'express' import { ChainId } from 'sushi/chain' -import { ROUTE_PROCESSOR_4_ADDRESS, RouteProcessor4ChainId } from 'sushi/config' +import { ROUTE_PROCESSOR_4_ADDRESS } from 'sushi/config' import { Type } from 'sushi/currency' import { NativeWrapProvider, + PoolCode, Router, RouterLiquiditySource, - makeAPI02Object, + makeAPI03Object, } from 'sushi/router' -import { isAddressFast } from 'sushi/serializer' import { MultiRoute } from 'sushi/tines' import { Address } from 'viem' +import { z } from 'zod' import { ExtractorClient } from '../../ExtractorClient.js' import swapRequestStatistics, { ResponseRejectReason, @@ -41,29 +42,29 @@ async function processUnknownToken( return token } -function handler( - qSchema: typeof querySchema4_2, - rpCode: typeof Router.routeProcessor4Params, - rpAddress: Address, -) { +const handler = ( + querySchema: typeof querySchema4_2, + routeProcessorParams: typeof Router.routeProcessor4Params, + routeProcessorAddress: Address, +) => { return (client: ExtractorClient) => { return async (req: Request, res: Response) => { res.setHeader('Cache-Control', 's-maxage=2, stale-while-revalidate=28') - let parsedData: any = undefined + + let poolCodesMap: Map = new Map() let bestRoute: MultiRoute | undefined = undefined - try { - const statistics = swapRequestStatistics.requestProcessingStart() - let parsed: ReturnType | undefined - try { - parsed = qSchema.safeParse(req.query) - } catch (_e) {} - if (!parsed || !parsed.success) { - swapRequestStatistics.requestRejected( - ResponseRejectReason.WRONG_INPUT_PARAMS, - ) - return res.status(422).send('Request parameters parsing error') - } + const statistics = swapRequestStatistics.requestProcessingStart() + const parsed = querySchema.safeParse(req.query) + if (!parsed.success) { + swapRequestStatistics.requestRejected( + ResponseRejectReason.WRONG_INPUT_PARAMS, + ) + console.log(parsed.error.format()) + return res.status(422).send('Request parameters parsing error') + } + + try { const { tokenIn: _tokenIn, tokenOut: _tokenOut, @@ -73,24 +74,8 @@ function handler( to, preferSushi, maxPriceImpact, - maxSlippage: _maxSlippage, + maxSlippage, } = parsed.data - parsedData = parsed.data - const maxSlippage = _maxSlippage ?? 0.005 // default value - - if (!isAddressFast(_tokenIn)) - return res - .status(422) - .send(`Incorrect address for tokenIn: ${_tokenIn}`) - if (!isAddressFast(_tokenOut)) - return res - .status(422) - .send(`Incorrect address for tokenOut: ${_tokenOut}`) - if (to !== undefined && !isAddressFast(to)) - return res.status(422).send(`Incorrect address for 'to': ${to}`) - if (amount <= 0) - return res.status(422).send(`Amount must be positive: ${amount}`) - if ( client.lastUpdatedTimestamp + MAX_TIME_WITHOUT_NETWORK_UPDATE < Date.now() @@ -127,7 +112,7 @@ function handler( ) } - const poolCodesMap = client.getKnownPoolsForTokens(tokenIn, tokenOut) + poolCodesMap = client.getKnownPoolsForTokens(tokenIn, tokenOut) nativeProvider .getCurrentPoolList() .forEach((p) => poolCodesMap.set(p.pool.uniqueID(), p)) @@ -135,7 +120,7 @@ function handler( bestRoute = preferSushi ? Router.findSpecialRoute( poolCodesMap, - CHAIN_ID as ChainId, + CHAIN_ID, tokenIn, amount, tokenOut, @@ -144,7 +129,7 @@ function handler( ) : Router.findBestRoute( poolCodesMap, - CHAIN_ID as ChainId, + CHAIN_ID, tokenIn, amount, tokenOut, @@ -157,25 +142,28 @@ function handler( ) bestRoute = Router.NoWayMultiRoute(tokenIn, tokenOut) - const json = makeAPI02Object( + const rpParams = to + ? routeProcessorParams( + poolCodesMap, + bestRoute, + tokenIn, + tokenOut, + to, + routeProcessorAddress, + [], + maxSlippage, + source ?? RouterLiquiditySource.Sender, + ) + : undefined + + const json = makeAPI03Object( bestRoute, - to - ? rpCode( - poolCodesMap, - bestRoute, - tokenIn, - tokenOut, - to, - rpAddress as Address, - [], - maxSlippage, - source ?? RouterLiquiditySource.Sender, - ) - : undefined, - rpAddress as Address, + rpParams, + routeProcessorAddress, + poolCodesMap, ) - // we want to return { route, tx: { from, to, gas, gasPrice, value, input } } + // we want to return { route, tx: { from, to, gas, gasPrice, data, value, } } swapRequestStatistics.requestWasProcessed(statistics, tokensAreKnown) return res.json(json) @@ -184,16 +172,24 @@ function handler( ResponseRejectReason.UNKNOWN_EXCEPTION, ) - const data: any = {} + const data: { + error: string | string[] | undefined + params: z.infer | undefined + route: MultiRoute | undefined + } = { + error: e instanceof Error ? e.stack?.split('\n') : `${e}`, + params: undefined, + route: undefined, + } try { data.error = e instanceof Error ? e.stack?.split('\n') : `${e}` - if (parsedData) data.params = parsedData - if (bestRoute) data.route = makeAPI02Object(bestRoute, undefined, '') + if (parsed.data) data.params = parsed.data + if (bestRoute) + data.route = makeAPI03Object(bestRoute, undefined, '', poolCodesMap) } catch (_e) {} Logger.error(CHAIN_ID, 'Routing crashed', safeSerialize(data), false) return res.status(500).send('Internal server error: Routing crashed') - //throw e } } } @@ -202,5 +198,5 @@ function handler( export const swapV4_2 = handler( querySchema4_2, Router.routeProcessor4Params, - ROUTE_PROCESSOR_4_ADDRESS[CHAIN_ID as RouteProcessor4ChainId], + ROUTE_PROCESSOR_4_ADDRESS[CHAIN_ID], ) diff --git a/apis/router/src/handlers/swap2/schema.ts b/apis/router/src/handlers/swap2/schema.ts index 433923567c..e0823a4f1f 100644 --- a/apis/router/src/handlers/swap2/schema.ts +++ b/apis/router/src/handlers/swap2/schema.ts @@ -1,4 +1,5 @@ import { RouterLiquiditySource } from 'sushi/router' +import { isAddressFast } from 'sushi/serializer' import type { Address } from 'viem' import z from 'zod' @@ -6,30 +7,44 @@ import z from 'zod' // maxPriceImpact - max current price impact (during route planning). Default - no control // maxSlippage - max slippage (during route processing). Default - 0.5% export const querySchema4_2 = z.object({ - tokenIn: z.string(), - tokenOut: z.string(), - amount: z.string().transform((amount) => BigInt(amount)), + tokenIn: z.custom
( + (val) => isAddressFast(val), + (val) => ({ message: `Incorrect address for tokenIn: ${val}` }), + ), + tokenOut: z.custom
( + (val) => isAddressFast(val), + (val) => ({ message: `Incorrect address for tokenIn: ${val}` }), + ), + amount: z.coerce.bigint().positive(), gasPrice: z.optional( z.coerce .number() .int('gasPrice should be integer') .gt(0, 'gasPrice should be positive'), ), - source: z.optional(z.nativeEnum(RouterLiquiditySource)), - to: z - .optional(z.string()) - .transform((to) => (to ? (to as Address) : undefined)), - preferSushi: z.optional(z.coerce.boolean()), + source: z + .optional(z.nativeEnum(RouterLiquiditySource)) + .default(RouterLiquiditySource.Sender), + to: z.optional( + z.custom
( + (val) => typeof val === 'string' && isAddressFast(val), + (val) => ({ message: `Incorrect address for 'to': ${val}` }), + ), + ), + preferSushi: z.optional(z.coerce.boolean()).default(true), maxPriceImpact: z.optional( z.coerce .number() .lt(1, 'maxPriceImpact should be lesser than 1') .gt(0, 'maxPriceImpact should be positive'), ), - maxSlippage: z.optional( - z.coerce - .number() - .lt(1, 'maxSlippage should be lesser than 1') - .gt(0, 'maxSlippage should be positive'), - ), + maxSlippage: z.coerce + .number() + .lt(1, 'maxSlippage should be lesser than 1') + .gt(0, 'maxSlippage should be positive') + .default(0.005), + // includeRoute: z.boolean().default(true), + // includeTx: z.boolean().default(true), }) + +export type querySchema4_2 = z.infer diff --git a/apps/web/next.config.mjs b/apps/web/next.config.mjs index ba51ec2d1d..145f406ee9 100644 --- a/apps/web/next.config.mjs +++ b/apps/web/next.config.mjs @@ -84,6 +84,16 @@ const nextConfig = bundleAnalyzer({ // ], // destination: '/aptos/:path*', // }, + { + source: '/:path*', + has: [ + { + type: 'host', + value: 'test.sushi.com', + }, + ], + destination: '/test/:path*', + }, // { // source: '/:path*', // has: [ diff --git a/apps/web/src/app/(non-evm)/aptos/layout.tsx b/apps/web/src/app/(non-evm)/aptos/layout.tsx index f227b74f17..1b2a648e8c 100644 --- a/apps/web/src/app/(non-evm)/aptos/layout.tsx +++ b/apps/web/src/app/(non-evm)/aptos/layout.tsx @@ -1,7 +1,7 @@ import { Metadata } from 'next' export const metadata: Metadata = { - title: 'Aptos', + title: 'SushiSwap | Aptos', } export default function Layout({ children }: { children: React.ReactNode }) { diff --git a/apps/web/src/app/(non-evm)/test/layout.tsx b/apps/web/src/app/(non-evm)/test/layout.tsx new file mode 100644 index 0000000000..0da74837dc --- /dev/null +++ b/apps/web/src/app/(non-evm)/test/layout.tsx @@ -0,0 +1,16 @@ +import { Container } from '@sushiswap/ui' +import { Metadata } from 'next' + +export const metadata: Metadata = { + title: 'SushiSwap | Test', +} + +export default function Layout({ children }: { children: React.ReactNode }) { + return ( +
+ + {children} + +
+ ) +} diff --git a/apps/web/src/app/(non-evm)/test/page.tsx b/apps/web/src/app/(non-evm)/test/page.tsx new file mode 100644 index 0000000000..64297aa866 --- /dev/null +++ b/apps/web/src/app/(non-evm)/test/page.tsx @@ -0,0 +1,5 @@ +import React from 'react' + +export default function Page() { + return

Test

+} diff --git a/apps/web/src/app/(non-evm)/test/swap/page.tsx b/apps/web/src/app/(non-evm)/test/swap/page.tsx new file mode 100644 index 0000000000..30d3546866 --- /dev/null +++ b/apps/web/src/app/(non-evm)/test/swap/page.tsx @@ -0,0 +1,5 @@ +import React from 'react' + +export default function Page() { + return

Swap

+} diff --git a/apps/web/src/app/(non-evm)/tron/layout.tsx b/apps/web/src/app/(non-evm)/tron/layout.tsx new file mode 100644 index 0000000000..060472a153 --- /dev/null +++ b/apps/web/src/app/(non-evm)/tron/layout.tsx @@ -0,0 +1,9 @@ +import { Metadata } from 'next' + +export const metadata: Metadata = { + title: 'SushiSwap | Tron', +} + +export default function Layout({ children }: { children: React.ReactNode }) { + return
{children}
+} diff --git a/apps/web/src/app/(non-evm)/tron/page.tsx b/apps/web/src/app/(non-evm)/tron/page.tsx new file mode 100644 index 0000000000..2e0f6e4364 --- /dev/null +++ b/apps/web/src/app/(non-evm)/tron/page.tsx @@ -0,0 +1,10 @@ +import { Container } from '@sushiswap/ui' +import React from 'react' + +export default function Page() { + return ( + +

Tron

+
+ ) +} diff --git a/k8s/chart/values.yaml b/k8s/chart/values.yaml index 1416eee395..973c0d0082 100644 --- a/k8s/chart/values.yaml +++ b/k8s/chart/values.yaml @@ -2,67 +2,67 @@ chains: - name: "ethereum" id: "1" - - name: "optimism" - id: "10" - - name: "cronos" - id: "25" - - name: "rootstock" - id: "30" - - name: "telos" - id: "40" - - name: "bsc" - id: "56" - - name: "gnosis" - id: "100" - - name: "thundercore" - id: "108" - - name: "fuse" - id: "122" - - name: "polygon" - id: "137" - - name: "bttc" - id: "199" - - name: "fantom" - id: "250" - - name: "boba" - id: "288" - - name: "filecoin" - id: "314" - - name: "polygon-zkevm" - id: "1101" - - name: "core" - id: "1116" - - name: "moonbeam" - id: "1284" - - name: "moonriver" - id: "1285" - - name: "metis" - id: "1088" - - name: "kava" - id: "2222" - - name: "zetachain" - id: "7000" - - name: "base" - id: "8453" - - name: "haqq" - id: "11235" - - name: "arbitrum" - id: "42161" - - name: "arbitrum-nova" - id: "42170" - - name: "celo" - id: "42220" - - name: "avalanche" - id: "43114" - - name: "linea" - id: "59144" - - name: "boba-bnb" - id: "56288" - - name: "blast" - id: "81457" - - name: "scroll" - id: "534352" - - name: "harmony" - id: "1666600000" - - name: "skale-europa" - id: "2046399126" \ No newline at end of file + # - name: "optimism" + # id: "10" + # - name: "cronos" + # id: "25" + # - name: "rootstock" + # id: "30" + # - name: "telos" + # id: "40" + # - name: "bsc" + # id: "56" + # - name: "gnosis" + # id: "100" + # - name: "thundercore" + # id: "108" + # - name: "fuse" + # id: "122" + # - name: "polygon" + # id: "137" + # - name: "bttc" + # id: "199" + # - name: "fantom" + # id: "250" + # - name: "boba" + # id: "288" + # - name: "filecoin" + # id: "314" + # - name: "polygon-zkevm" + # id: "1101" + # - name: "core" + # id: "1116" + # - name: "moonbeam" + # id: "1284" + # - name: "moonriver" + # id: "1285" + # - name: "metis" + # id: "1088" + # - name: "kava" + # id: "2222" + # - name: "zetachain" + # id: "7000" + # - name: "base" + # id: "8453" + # - name: "haqq" + # id: "11235" + # - name: "arbitrum" + # id: "42161" + # - name: "arbitrum-nova" + # id: "42170" + # - name: "celo" + # id: "42220" + # - name: "avalanche" + # id: "43114" + # - name: "linea" + # id: "59144" + # - name: "boba-bnb" + # id: "56288" + # - name: "blast" + # id: "81457" + # - name: "scroll" + # id: "534352" + # - name: "harmony" + # id: "1666600000" + # - name: "skale-europa" + # id: "2046399126" \ No newline at end of file diff --git a/packages/sushi/src/router/makeAPI02Object.ts b/packages/sushi/src/router/makeAPI02Object.ts index 9d6ace3d0d..bfa4c74eb4 100644 --- a/packages/sushi/src/router/makeAPI02Object.ts +++ b/packages/sushi/src/router/makeAPI02Object.ts @@ -1,4 +1,7 @@ +import { Token } from '../currency/Token.js' import { MultiRoute, RToken, RouteLeg, RouteStatus } from '../tines/index.js' +import { LiquidityProviders } from './liquidity-providers/LiquidityProvider.js' +import { PoolCode } from './pool-codes/PoolCode.js' import { RPParams } from './router.js' function makeAPI02Token(token: RToken) { @@ -25,8 +28,24 @@ function makeAPI02Leg(leg: RouteLeg, tokens: TokenConvertor) { } } +function makeAPI03Leg( + leg: RouteLeg, + tokens: TokenConvertor, + liquidityProviders: LiquidityProviderConvertor, +) { + return { + liquidityProvider: liquidityProviders.getLiquidityProviderIndex( + leg.uniqueId, + ), + poolAddress: leg.poolAddress, + tokenFrom: tokens.getTokenIndex(leg.tokenFrom), + tokenTo: tokens.getTokenIndex(leg.tokenTo), + share: leg.absolutePortion, + } +} + class TokenConvertor { - tokens: ReturnType[] = [] + tokens: Pick[] = [] tokenMap = new Map() _tokenId(t: RToken) { @@ -49,6 +68,32 @@ class TokenConvertor { } } +class LiquidityProviderConvertor { + liquidityProviders: LiquidityProviders[] = [] + liquidityProviderMap = new Map() + idToLiquidityProvider = new Map() + + addLiquidityProvider(id: string, liquidityProvider: LiquidityProviders) { + if (this.liquidityProviderMap.get(liquidityProvider) === undefined) { + this.liquidityProviders.push(liquidityProvider) + + this.liquidityProviderMap.set( + liquidityProvider, + this.liquidityProviders.length - 1, + ) + } + this.idToLiquidityProvider.set(id, liquidityProvider) + } + + getLiquidityProviderIndex(id: string) { + return this.liquidityProviderMap.get(this.idToLiquidityProvider.get(id)!) + } + + geLiquidityProviderList() { + return this.liquidityProviders + } +} + export function makeAPI02Object( route: MultiRoute, rpParams: RPParams | undefined, @@ -93,3 +138,56 @@ export function makeAPI02Object( return APIObj } + +export function makeAPI03Object( + route: MultiRoute, + rpParams: RPParams | undefined, + routeProcessorAddr: string, + poolCodesMap: Map, +) { + if (route.status === RouteStatus.NoWay) return { status: RouteStatus.NoWay } + const tokens = new TokenConvertor() + const liquidityProviders = new LiquidityProviderConvertor() + route.legs.forEach((l) => { + tokens.addToken(l.tokenFrom) + tokens.addToken(l.tokenTo) + liquidityProviders.addLiquidityProvider( + l.uniqueId, + poolCodesMap.get(l.uniqueId)!.liquidityProvider, + ) + }) + + const APIObj = { + status: route.status, + tokens: tokens.getTokenList(), + liquidityProviders: liquidityProviders.geLiquidityProviderList(), + tokenFrom: tokens.getTokenIndex(route.fromToken), + tokenTo: tokens.getTokenIndex(route.toToken), + + primaryPrice: route.primaryPrice, + swapPrice: route.swapPrice, + priceImpact: route.priceImpact, + + amountIn: route.amountInBI.toString(), + assumedAmountOut: route.amountOutBI.toString(), + gasSpent: route.gasSpent, + + route: route.legs.map((l) => makeAPI03Leg(l, tokens, liquidityProviders)), + } as any + if (rpParams !== undefined) { + APIObj.routeProcessorAddr = routeProcessorAddr + APIObj.routeProcessorArgs = { + tokenIn: rpParams.tokenIn, + amountIn: rpParams.amountIn.toString(), + tokenOut: rpParams.tokenOut, + amountOutMin: rpParams.amountOutMin.toString(), + to: rpParams.to, + routeCode: rpParams.routeCode, + txdata: rpParams.data, + } + if (rpParams.value !== undefined) + APIObj.routeProcessorArgs.value = rpParams.value.toString() + } + + return APIObj +} diff --git a/packages/sushi/src/router/router.ts b/packages/sushi/src/router/router.ts index d79c79c03f..894ef196a9 100644 --- a/packages/sushi/src/router/router.ts +++ b/packages/sushi/src/router/router.ts @@ -211,7 +211,7 @@ export class Router { ...route, legs: route.legs.map((l) => ({ ...l, - poolName: poolCodesMap.get(l.poolAddress)?.poolName ?? 'Unknown Pool', + poolName: poolCodesMap.get(l.uniqueId)?.poolName ?? 'Unknown Pool', })), } } diff --git a/packages/sushi/src/serializer/AddressValidation.ts b/packages/sushi/src/serializer/AddressValidation.ts index aa3ec0d4e6..cfd5b3a676 100644 --- a/packages/sushi/src/serializer/AddressValidation.ts +++ b/packages/sushi/src/serializer/AddressValidation.ts @@ -1,5 +1,5 @@ const addressRegex = /^0x[a-fA-F0-9]{40}$/ -export function isAddressFast(addr: string | undefined) { - return addr !== undefined && addressRegex.test(addr) +export function isAddressFast(addr: unknown) { + return typeof addr === 'string' && addressRegex.test(addr) } From 52a6080a7595c937ad833cb459bb7f1a01e4d5fa Mon Sep 17 00:00:00 2001 From: 0xMasayoshi <0xMasayoshi@protonmail.com> Date: Sun, 28 Jul 2024 01:26:09 +0700 Subject: [PATCH 007/125] chore: use cjs in RouteProcessor pkg --- protocols/route-processor/deploy/RouteProcessor.ts | 3 ++- protocols/route-processor/deploy/RouteProcessor3.ts | 2 +- protocols/route-processor/deploy/RouteProcessor3_1.ts | 2 +- protocols/route-processor/deploy/RouteProcessor3_2.ts | 2 +- protocols/route-processor/package.json | 1 - 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/protocols/route-processor/deploy/RouteProcessor.ts b/protocols/route-processor/deploy/RouteProcessor.ts index 98dea073db..ef036f52ff 100644 --- a/protocols/route-processor/deploy/RouteProcessor.ts +++ b/protocols/route-processor/deploy/RouteProcessor.ts @@ -1,12 +1,13 @@ import { DeployFunction } from 'hardhat-deploy/dist/types' import { HardhatRuntimeEnvironment } from 'hardhat/types' -import { BENTOBOX_ADDRESS, isBentoBoxChainId } from 'sushi/config' const func: DeployFunction = async ({ getNamedAccounts, deployments, getChainId, }: HardhatRuntimeEnvironment) => { + const { BENTOBOX_ADDRESS, isBentoBoxChainId } = await import('sushi/config') + const { deploy } = deployments const { deployer } = await getNamedAccounts() diff --git a/protocols/route-processor/deploy/RouteProcessor3.ts b/protocols/route-processor/deploy/RouteProcessor3.ts index 30d07b66fd..e89558eb06 100644 --- a/protocols/route-processor/deploy/RouteProcessor3.ts +++ b/protocols/route-processor/deploy/RouteProcessor3.ts @@ -1,12 +1,12 @@ import { DeployFunction } from 'hardhat-deploy/dist/types' import { HardhatRuntimeEnvironment } from 'hardhat/types' -import { BENTOBOX_ADDRESS, isBentoBoxChainId } from 'sushi/config' const func: DeployFunction = async ({ getNamedAccounts, deployments, getChainId, }: HardhatRuntimeEnvironment) => { + const { BENTOBOX_ADDRESS, isBentoBoxChainId } = await import('sushi/config') const { deploy } = deployments const { deployer } = await getNamedAccounts() diff --git a/protocols/route-processor/deploy/RouteProcessor3_1.ts b/protocols/route-processor/deploy/RouteProcessor3_1.ts index e939411fff..d32fccef2f 100644 --- a/protocols/route-processor/deploy/RouteProcessor3_1.ts +++ b/protocols/route-processor/deploy/RouteProcessor3_1.ts @@ -1,6 +1,5 @@ import { DeployFunction } from 'hardhat-deploy/dist/types' import { HardhatRuntimeEnvironment } from 'hardhat/types' -import { BENTOBOX_ADDRESS, isBentoBoxChainId } from 'sushi/config' const func: DeployFunction = async ({ getNamedAccounts, @@ -8,6 +7,7 @@ const func: DeployFunction = async ({ run, getChainId, }: HardhatRuntimeEnvironment) => { + const { BENTOBOX_ADDRESS, isBentoBoxChainId } = await import('sushi/config') const { deploy } = deployments const { deployer } = await getNamedAccounts() diff --git a/protocols/route-processor/deploy/RouteProcessor3_2.ts b/protocols/route-processor/deploy/RouteProcessor3_2.ts index d908331647..52cf8e2a91 100644 --- a/protocols/route-processor/deploy/RouteProcessor3_2.ts +++ b/protocols/route-processor/deploy/RouteProcessor3_2.ts @@ -1,6 +1,5 @@ import { DeployFunction } from 'hardhat-deploy/dist/types' import { HardhatRuntimeEnvironment } from 'hardhat/types' -import { BENTOBOX_ADDRESS, isBentoBoxChainId } from 'sushi/config' const func: DeployFunction = async ({ getNamedAccounts, @@ -8,6 +7,7 @@ const func: DeployFunction = async ({ run, getChainId, }: HardhatRuntimeEnvironment) => { + const { BENTOBOX_ADDRESS, isBentoBoxChainId } = await import('sushi/config') const { deploy } = deployments const { deployer } = await getNamedAccounts() diff --git a/protocols/route-processor/package.json b/protocols/route-processor/package.json index 7f4641e4f4..7886167ed7 100644 --- a/protocols/route-processor/package.json +++ b/protocols/route-processor/package.json @@ -5,7 +5,6 @@ "description": "Router", "license": "UNLICENSED", "author": "Ilya Lyalin", - "type": "module", "files": [ "artifacts", "contracts", From c2743042a567b6ba57ac399f07bb186fd1f7dd7a Mon Sep 17 00:00:00 2001 From: 0xMasayoshi <0xMasayoshi@protonmail.com> Date: Tue, 30 Jul 2024 01:36:10 +0700 Subject: [PATCH 008/125] feat: RP5 deployments --- config/hardhat/index.js | 80 +- protocols/route-processor/.env.example | 3 +- .../route-processor/deploy/RouteProcessor5.ts | 62 ++ .../arbitrum-nova/RouteProcessor5.json | 704 +++++++++++++++++ .../e556d43a3caf4f1fb4f12d632d103b28.json | 80 ++ .../deployments/arbitrum/RouteProcessor5.json | 704 +++++++++++++++++ .../e556d43a3caf4f1fb4f12d632d103b28.json | 80 ++ .../avalanche/RouteProcessor5.json | 704 +++++++++++++++++ .../e556d43a3caf4f1fb4f12d632d103b28.json | 80 ++ .../deployments/base/RouteProcessor5.json | 704 +++++++++++++++++ .../e556d43a3caf4f1fb4f12d632d103b28.json | 80 ++ .../deployments/blast/RouteProcessor5.json | 704 +++++++++++++++++ .../e556d43a3caf4f1fb4f12d632d103b28.json | 80 ++ .../deployments/boba-bnb/RouteProcessor5.json | 704 +++++++++++++++++ .../e556d43a3caf4f1fb4f12d632d103b28.json | 80 ++ .../deployments/boba/RouteProcessor5.json | 704 +++++++++++++++++ .../e556d43a3caf4f1fb4f12d632d103b28.json | 80 ++ .../deployments/bsc/RouteProcessor5.json | 704 +++++++++++++++++ .../e556d43a3caf4f1fb4f12d632d103b28.json | 80 ++ .../deployments/bttc/RouteProcessor5.json | 719 ++++++++++++++++++ .../e556d43a3caf4f1fb4f12d632d103b28.json | 80 ++ .../deployments/celo/RouteProcessor5.json | 704 +++++++++++++++++ .../e556d43a3caf4f1fb4f12d632d103b28.json | 80 ++ .../deployments/core/RouteProcessor5.json | 704 +++++++++++++++++ .../e556d43a3caf4f1fb4f12d632d103b28.json | 80 ++ .../deployments/ethereum/RouteProcessor5.json | 704 +++++++++++++++++ .../e556d43a3caf4f1fb4f12d632d103b28.json | 80 ++ .../deployments/fantom/RouteProcessor5.json | 704 +++++++++++++++++ .../e556d43a3caf4f1fb4f12d632d103b28.json | 80 ++ .../deployments/filecoin/RouteProcessor5.json | 704 +++++++++++++++++ .../e556d43a3caf4f1fb4f12d632d103b28.json | 80 ++ .../deployments/fuse/RouteProcessor5.json | 704 +++++++++++++++++ .../e556d43a3caf4f1fb4f12d632d103b28.json | 80 ++ .../deployments/gnosis/RouteProcessor5.json | 704 +++++++++++++++++ .../e556d43a3caf4f1fb4f12d632d103b28.json | 80 ++ .../deployments/haqq/RouteProcessor5.json | 704 +++++++++++++++++ .../e556d43a3caf4f1fb4f12d632d103b28.json | 80 ++ .../deployments/harmony/RouteProcessor5.json | 704 +++++++++++++++++ .../e556d43a3caf4f1fb4f12d632d103b28.json | 80 ++ .../deployments/kava/RouteProcessor5.json | 704 +++++++++++++++++ .../e556d43a3caf4f1fb4f12d632d103b28.json | 80 ++ .../deployments/linea/RouteProcessor5.json | 704 +++++++++++++++++ .../e556d43a3caf4f1fb4f12d632d103b28.json | 80 ++ .../deployments/metis/RouteProcessor5.json | 704 +++++++++++++++++ .../e556d43a3caf4f1fb4f12d632d103b28.json | 80 ++ .../deployments/moonbeam/RouteProcessor5.json | 704 +++++++++++++++++ .../e556d43a3caf4f1fb4f12d632d103b28.json | 80 ++ .../moonriver/RouteProcessor5.json | 704 +++++++++++++++++ .../e556d43a3caf4f1fb4f12d632d103b28.json | 80 ++ .../deployments/optimism/RouteProcessor5.json | 704 +++++++++++++++++ .../e556d43a3caf4f1fb4f12d632d103b28.json | 80 ++ .../deployments/polygon/RouteProcessor5.json | 719 ++++++++++++++++++ .../e556d43a3caf4f1fb4f12d632d103b28.json | 80 ++ .../polygonzkevm/RouteProcessor5.json | 704 +++++++++++++++++ .../e556d43a3caf4f1fb4f12d632d103b28.json | 80 ++ .../rootstock/RouteProcessor5.json | 704 +++++++++++++++++ .../e556d43a3caf4f1fb4f12d632d103b28.json | 80 ++ .../deployments/scroll/RouteProcessor5.json | 704 +++++++++++++++++ .../e556d43a3caf4f1fb4f12d632d103b28.json | 80 ++ .../deployments/sepolia/.chainId | 1 + .../deployments/sepolia/RouteProcessor5.json | 704 +++++++++++++++++ .../e556d43a3caf4f1fb4f12d632d103b28.json | 80 ++ .../skale-europa/RouteProcessor5.json | 704 +++++++++++++++++ .../e556d43a3caf4f1fb4f12d632d103b28.json | 80 ++ .../deployments/telos/RouteProcessor5.json | 704 +++++++++++++++++ .../e556d43a3caf4f1fb4f12d632d103b28.json | 80 ++ .../thundercore/RouteProcessor5.json | 704 +++++++++++++++++ .../e556d43a3caf4f1fb4f12d632d103b28.json | 80 ++ .../zetachain/RouteProcessor5.json | 704 +++++++++++++++++ .../e556d43a3caf4f1fb4f12d632d103b28.json | 80 ++ 70 files changed, 26042 insertions(+), 6 deletions(-) create mode 100644 protocols/route-processor/deploy/RouteProcessor5.ts create mode 100644 protocols/route-processor/deployments/arbitrum-nova/RouteProcessor5.json create mode 100644 protocols/route-processor/deployments/arbitrum-nova/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json create mode 100644 protocols/route-processor/deployments/arbitrum/RouteProcessor5.json create mode 100644 protocols/route-processor/deployments/arbitrum/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json create mode 100644 protocols/route-processor/deployments/avalanche/RouteProcessor5.json create mode 100644 protocols/route-processor/deployments/avalanche/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json create mode 100644 protocols/route-processor/deployments/base/RouteProcessor5.json create mode 100644 protocols/route-processor/deployments/base/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json create mode 100644 protocols/route-processor/deployments/blast/RouteProcessor5.json create mode 100644 protocols/route-processor/deployments/blast/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json create mode 100644 protocols/route-processor/deployments/boba-bnb/RouteProcessor5.json create mode 100644 protocols/route-processor/deployments/boba-bnb/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json create mode 100644 protocols/route-processor/deployments/boba/RouteProcessor5.json create mode 100644 protocols/route-processor/deployments/boba/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json create mode 100644 protocols/route-processor/deployments/bsc/RouteProcessor5.json create mode 100644 protocols/route-processor/deployments/bsc/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json create mode 100644 protocols/route-processor/deployments/bttc/RouteProcessor5.json create mode 100644 protocols/route-processor/deployments/bttc/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json create mode 100644 protocols/route-processor/deployments/celo/RouteProcessor5.json create mode 100644 protocols/route-processor/deployments/celo/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json create mode 100644 protocols/route-processor/deployments/core/RouteProcessor5.json create mode 100644 protocols/route-processor/deployments/core/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json create mode 100644 protocols/route-processor/deployments/ethereum/RouteProcessor5.json create mode 100644 protocols/route-processor/deployments/ethereum/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json create mode 100644 protocols/route-processor/deployments/fantom/RouteProcessor5.json create mode 100644 protocols/route-processor/deployments/fantom/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json create mode 100644 protocols/route-processor/deployments/filecoin/RouteProcessor5.json create mode 100644 protocols/route-processor/deployments/filecoin/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json create mode 100644 protocols/route-processor/deployments/fuse/RouteProcessor5.json create mode 100644 protocols/route-processor/deployments/fuse/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json create mode 100644 protocols/route-processor/deployments/gnosis/RouteProcessor5.json create mode 100644 protocols/route-processor/deployments/gnosis/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json create mode 100644 protocols/route-processor/deployments/haqq/RouteProcessor5.json create mode 100644 protocols/route-processor/deployments/haqq/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json create mode 100644 protocols/route-processor/deployments/harmony/RouteProcessor5.json create mode 100644 protocols/route-processor/deployments/harmony/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json create mode 100644 protocols/route-processor/deployments/kava/RouteProcessor5.json create mode 100644 protocols/route-processor/deployments/kava/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json create mode 100644 protocols/route-processor/deployments/linea/RouteProcessor5.json create mode 100644 protocols/route-processor/deployments/linea/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json create mode 100644 protocols/route-processor/deployments/metis/RouteProcessor5.json create mode 100644 protocols/route-processor/deployments/metis/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json create mode 100644 protocols/route-processor/deployments/moonbeam/RouteProcessor5.json create mode 100644 protocols/route-processor/deployments/moonbeam/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json create mode 100644 protocols/route-processor/deployments/moonriver/RouteProcessor5.json create mode 100644 protocols/route-processor/deployments/moonriver/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json create mode 100644 protocols/route-processor/deployments/optimism/RouteProcessor5.json create mode 100644 protocols/route-processor/deployments/optimism/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json create mode 100644 protocols/route-processor/deployments/polygon/RouteProcessor5.json create mode 100644 protocols/route-processor/deployments/polygon/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json create mode 100644 protocols/route-processor/deployments/polygonzkevm/RouteProcessor5.json create mode 100644 protocols/route-processor/deployments/polygonzkevm/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json create mode 100644 protocols/route-processor/deployments/rootstock/RouteProcessor5.json create mode 100644 protocols/route-processor/deployments/rootstock/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json create mode 100644 protocols/route-processor/deployments/scroll/RouteProcessor5.json create mode 100644 protocols/route-processor/deployments/scroll/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json create mode 100644 protocols/route-processor/deployments/sepolia/.chainId create mode 100644 protocols/route-processor/deployments/sepolia/RouteProcessor5.json create mode 100644 protocols/route-processor/deployments/sepolia/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json create mode 100644 protocols/route-processor/deployments/skale-europa/RouteProcessor5.json create mode 100644 protocols/route-processor/deployments/skale-europa/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json create mode 100644 protocols/route-processor/deployments/telos/RouteProcessor5.json create mode 100644 protocols/route-processor/deployments/telos/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json create mode 100644 protocols/route-processor/deployments/thundercore/RouteProcessor5.json create mode 100644 protocols/route-processor/deployments/thundercore/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json create mode 100644 protocols/route-processor/deployments/zetachain/RouteProcessor5.json create mode 100644 protocols/route-processor/deployments/zetachain/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json diff --git a/config/hardhat/index.js b/config/hardhat/index.js index ddc7363f7f..d30e318f94 100644 --- a/config/hardhat/index.js +++ b/config/hardhat/index.js @@ -11,7 +11,12 @@ require('@matterlabs/hardhat-zksync-deploy') require('@matterlabs/hardhat-zksync-solc') const accounts = process.env.PRIVATE_KEY - ? [process.env.PRIVATE_KEY] + ? [ + process.env.PRIVATE_KEY, + ...(process.env.FUNDER_PRIVATE_KEY + ? [process.env.FUNDER_PRIVATE_KEY] + : []), + ] : { mnemonic: process.env.MNEMONIC || @@ -29,7 +34,7 @@ module.exports.defaultConfig = { network: 'kava', chainId: 2222, urls: { - apiURL: 'https://kavascan.com/api', + apiURL: 'https://api.verify.mintscan.io/evm/api/0x8ae', browserURL: 'https://kavascan.com', }, }, @@ -171,6 +176,47 @@ module.exports.defaultConfig = { browserURL: 'https://blastscan.io', }, }, + { + network: 'harmony', + chainId: 1666600000, + urls: { + apiURL: 'https://explorer.harmony.one/api', + browserURL: 'https://explorer.harmony.one', + }, + }, + { + network: 'linea', + chainId: 59144, + urls: { + apiURL: 'https://api.lineascan.build/api', + browserURL: 'https://lineascan.build/', + }, + }, + { + network: 'metis', + chainId: 1088, + urls: { + apiURL: 'https://rootstock.blockscout.com/api', + browserURL: 'https://rootstock.blockscout.com', + }, + }, + { + network: 'rootstock', + chainId: 30, + urls: { + apiURL: + 'https://api.routescan.io/v2/network/mainnet/evm/1088/etherscan', + browserURL: 'https://explorer.metis.io', + }, + }, + { + network: 'skale-europa', + chainId: 2046399126, + urls: { + apiURL: 'https://elated-tan-skat.explorer.mainnet.skalenodes.com/api', + browserURL: 'https://elated-tan-skat.explorer.mainnet.skalenodes.com', + }, + }, ], apiKey: { mainnet: process.env.ETHERSCAN_API_KEY || '', @@ -178,6 +224,7 @@ module.exports.defaultConfig = { rinkeby: process.env.ETHERSCAN_API_KEY || '', goerli: process.env.ETHERSCAN_API_KEY || '', kovan: process.env.ETHERSCAN_API_KEY || '', + sepolia: process.env.ETHERSCAN_API_KEY || '', // binance smart chain bsc: process.env.BSCSCAN_API_KEY || '', bscTestnet: process.env.BSCSCAN_API_KEY || '', @@ -189,7 +236,6 @@ module.exports.defaultConfig = { ftmTestnet: process.env.FTMSCAN_API_KEY || '', // optimism optimisticEthereum: process.env.OPTIMISTIC_ETHERSCAN_API_KEY || '', - optimisticKovan: process.env.OPTIMISTIC_ETHERSCAN_API_KEY || '', // polygon polygon: process.env.POLYGONSCAN_API_KEY || '', polygonMumbai: process.env.POLYGONSCAN_API_KEY || '', @@ -229,6 +275,8 @@ module.exports.defaultConfig = { fuse: 'api-key', boba: 'api-key', 'boba-bnb': 'api-key', + rootstock: 'api-key', + 'skale-europa': 'api-key', }, }, tenderly: { @@ -338,6 +386,13 @@ module.exports.defaultConfig = { tags: ['staging'], gasMultiplier: 2, }, + sepolia: { + url: 'https://rpc.sepolia.org', + accounts, + chainId: 11155111, + live: true, + saveDeployments: true, + }, fantom: { url: 'https://rpcapi.fantom.network', accounts, @@ -355,7 +410,7 @@ module.exports.defaultConfig = { gasMultiplier: 2, }, polygon: { - url: 'https://rpc-mainnet.maticvigil.com', + url: 'https://polygon.llamarpc.com', accounts, chainId: 137, live: true, @@ -427,7 +482,7 @@ module.exports.defaultConfig = { gasMultiplier: 2, }, harmony: { - url: 'https://api.s0.t.hmny.io', + url: 'https://rpc.ankr.com/harmony', accounts, chainId: 1666600000, live: true, @@ -658,10 +713,25 @@ module.exports.defaultConfig = { live: true, saveDeployments: true, }, + rootstock: { + url: 'https://mycrypto.rsk.co', + accounts, + chainId: 30, + live: true, + saveDeployments: true, + }, + 'skale-europa': { + url: 'https://mainnet.skalenodes.com/v1/elated-tan-skat', + accounts, + chainId: 2046399126, + live: true, + saveDeployments: true, + }, }, namedAccounts: { // e.g. ledger://0x18dd4e0Eb8699eA4fee238dE41ecF115e32272F8 deployer: process.env.LEDGER || { default: 0 }, + funder: { default: 1 }, alice: { default: 1, }, diff --git a/protocols/route-processor/.env.example b/protocols/route-processor/.env.example index ce1584298c..f5494acaa3 100644 --- a/protocols/route-processor/.env.example +++ b/protocols/route-processor/.env.example @@ -7,4 +7,5 @@ MNEMONIC="test test test test test test test test test test test junk" REPORT_GAS=false TENDERLY_PROJECT= TENDERLY_USERNAME= -PRIVATE_KEY= \ No newline at end of file +PRIVATE_KEY= +FUNDER_PRIVATE_KEY= \ No newline at end of file diff --git a/protocols/route-processor/deploy/RouteProcessor5.ts b/protocols/route-processor/deploy/RouteProcessor5.ts new file mode 100644 index 0000000000..565074158d --- /dev/null +++ b/protocols/route-processor/deploy/RouteProcessor5.ts @@ -0,0 +1,62 @@ +import { DeployFunction } from 'hardhat-deploy/dist/types' +import { HardhatRuntimeEnvironment } from 'hardhat/types' + +const func: DeployFunction = async ({ + ethers, + getNamedSigners, + deployments, + run, +}: HardhatRuntimeEnvironment) => { + const { deploy } = deployments + const { deployer, funder } = await ethers.getNamedSigners() + + if (!deployer || !funder) throw new Error('Signers not configured') + + console.log('deployer', deployer.address) + console.log('funder', funder.address) + + const args = ['0x0000000000000000000000000000000000000000', []] + + const RP5 = await ethers.getContractFactory('RouteProcessor5') + + const [estGasLimit, gasPrice] = await Promise.all([ + funder.estimateGas(RP5.getDeployTransaction(...args)), + funder.getGasPrice(), + ]) + + const estGasLimitWithBuffer = estGasLimit.mul(120).div(100) + + const estGasNeeded = estGasLimitWithBuffer.mul(gasPrice) + + console.log(`Est. gas for deployment: ${estGasNeeded}`) + + const tx = await funder.sendTransaction({ + to: deployer.address, + value: estGasNeeded, + gasPrice, + }) + + await tx.wait() + + console.log(`Funding transaction completed: ${tx.hash}`) + + const { address } = await deploy('RouteProcessor5', { + from: deployer.address, + args, + estimatedGasLimit: estGasLimitWithBuffer, + gasPrice, + }) + + console.log(`RouteProcessor5 deployed to ${address}`) + + await run('verify:verify', { + address, + constructorArguments: args, + }) + + console.log('RouteProcessor5 verified') +} + +func.tags = ['RouteProcessor5'] + +export default func diff --git a/protocols/route-processor/deployments/arbitrum-nova/RouteProcessor5.json b/protocols/route-processor/deployments/arbitrum-nova/RouteProcessor5.json new file mode 100644 index 0000000000..650cf5f3d0 --- /dev/null +++ b/protocols/route-processor/deployments/arbitrum-nova/RouteProcessor5.json @@ -0,0 +1,704 @@ +{ + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_bentoBox", + "type": "address" + }, + { + "internalType": "address[]", + "name": "priviledgedUserList", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "MinimalOutputBalanceViolation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Route", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "algebraSwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bentoBox", + "outputs": [ + { + "internalType": "contract IBentoBoxMinimal", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "pancakeV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "priviledgedUsers", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueInput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "priviledge", + "type": "bool" + } + ], + "name": "setPriviledge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "transferValueAndprocessRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0xc5c7206a538626c23a269a8a8a21994836570f4f51ba44f276b4a6f945f0043b", + "receipt": { + "to": null, + "from": "0x282607716D9B4fDD0B094d5864fac56313f5e665", + "contractAddress": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "transactionIndex": 1, + "gasUsed": "3513162", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000020000000000000000000000000000000000000001000000000000000000000000000000000000000000040000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000000000000000000000000000", + "blockHash": "0x697bafdd508269ecf1348fb174f2aac09382fcb9334ccf3df26031d71c0ccb09", + "transactionHash": "0xc5c7206a538626c23a269a8a8a21994836570f4f51ba44f276b4a6f945f0043b", + "logs": [ + { + "transactionIndex": 1, + "blockNumber": 74671959, + "transactionHash": "0xc5c7206a538626c23a269a8a8a21994836570f4f51ba44f276b4a6f945f0043b", + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000282607716d9b4fdd0b094d5864fac56313f5e665" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0x697bafdd508269ecf1348fb174f2aac09382fcb9334ccf3df26031d71c0ccb09" + } + ], + "blockNumber": 74671959, + "cumulativeGasUsed": "3513162", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000000", + [] + ], + "numDeployments": 1, + "solcInputHash": "e556d43a3caf4f1fb4f12d632d103b28", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bentoBox\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"priviledgedUserList\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"MinimalOutputBalanceViolation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"Route\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"algebraSwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"pancakeV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"priviledgedUsers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"priviledge\",\"type\":\"bool\"}],\"name\":\"setPriviledge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"transferValueAndprocessRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"Ilya Lyalin\",\"kind\":\"dev\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IAlgebraPoolActions#swap call\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the PancakeV3Pool#swap call\"}},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"route\":\"Route to process\",\"to\":\"Where to transfer output tokens\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IUniswapV3PoolActions#swap call\"}}},\"title\":\"A route processor for the Sushi Aggregator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\"},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Processes the route generated off-chain. Has a lock\"},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value of input tokens to and then processes the route\"},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"processes the route and sends amount of output token to \"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value to and then processes the route\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RouteProcessor5.sol\":\"RouteProcessor5\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\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 Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.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 function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\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\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\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 * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\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\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/InputStream.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\n/** @notice Simple read stream */\\nlibrary InputStream {\\n\\n /** @notice Creates stream from data\\n * @param data data\\n */\\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\\n assembly {\\n stream := mload(0x40)\\n mstore(0x40, add(stream, 64))\\n mstore(stream, data)\\n let length := mload(data)\\n mstore(add(stream, 32), add(data, length))\\n }\\n }\\n\\n /** @notice Checks if stream is not empty\\n * @param stream stream\\n */\\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\\n uint256 pos;\\n uint256 finish;\\n assembly {\\n pos := mload(stream)\\n finish := mload(add(stream, 32))\\n }\\n return pos < finish;\\n }\\n\\n /** @notice Reads uint8 from the stream\\n * @param stream stream\\n */\\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 1)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint16 from the stream\\n * @param stream stream\\n */\\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 2)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint24 from the stream\\n * @param stream stream\\n */\\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 3)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint32 from the stream\\n * @param stream stream\\n */\\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 4)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint256 from the stream\\n * @param stream stream\\n */\\n function readUint(uint256 stream) internal pure returns (uint256 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes32 from the stream\\n * @param stream stream\\n */\\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads address from the stream\\n * @param stream stream\\n */\\n function readAddress(uint256 stream) internal pure returns (address res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 20)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes from the stream\\n * @param stream stream\\n */\\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\\n assembly {\\n let pos := mload(stream)\\n res := add(pos, 32)\\n let length := mload(res)\\n mstore(stream, add(res, length))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x24e24bd0e49cbddacbf3b26bcd4bdffac63d11f3259bc05bc93c0835e8ff5300\",\"license\":\"UNLICENSED\"},\"contracts/RouteProcessor5.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '../interfaces/IUniswapV2Pair.sol';\\nimport '../interfaces/IUniswapV3Pool.sol';\\nimport '../interfaces/ITridentCLPool.sol';\\nimport '../interfaces/IBentoBoxMinimal.sol';\\nimport '../interfaces/IPool.sol';\\nimport '../interfaces/IWETH.sol';\\nimport '../interfaces/ICurve.sol';\\nimport './InputStream.sol';\\nimport './Utils.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\\n\\nuint8 constant LOCKED = 2;\\nuint8 constant NOT_LOCKED = 1;\\nuint8 constant PAUSED = 2;\\nuint8 constant NOT_PAUSED = 1;\\n\\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\nuint160 constant MIN_SQRT_RATIO = 4295128739;\\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n/// @title A route processor for the Sushi Aggregator\\n/// @author Ilya Lyalin\\ncontract RouteProcessor5 is Ownable {\\n using SafeERC20 for IERC20;\\n using Utils for IERC20;\\n using Utils for address;\\n using SafeERC20 for IERC20Permit;\\n using InputStream for uint256;\\n\\n event Route(\\n address indexed from, \\n address to, \\n address indexed tokenIn, \\n address indexed tokenOut, \\n uint256 amountIn, \\n uint256 amountOutMin,\\n uint256 amountOut\\n );\\n\\n error MinimalOutputBalanceViolation(uint256 amountOut);\\n\\n IBentoBoxMinimal public immutable bentoBox;\\n mapping (address => bool) public priviledgedUsers;\\n address private lastCalledPool;\\n\\n uint8 private unlocked = NOT_LOCKED;\\n uint8 private paused = NOT_PAUSED;\\n modifier lock() {\\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\\n unlocked = LOCKED;\\n _;\\n unlocked = NOT_LOCKED;\\n }\\n\\n modifier onlyOwnerOrPriviledgedUser() {\\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \\\"RP: caller is not the owner or a privileged user\\\");\\n _;\\n }\\n\\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\\n bentoBox = IBentoBoxMinimal(_bentoBox);\\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n\\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\\n priviledgedUsers[priviledgedUserList[i]] = true;\\n }\\n }\\n\\n function setPriviledge(address user, bool priviledge) external onlyOwner {\\n priviledgedUsers[user] = priviledge;\\n }\\n\\n function pause() external onlyOwnerOrPriviledgedUser {\\n paused = PAUSED;\\n }\\n\\n function resume() external onlyOwnerOrPriviledgedUser {\\n paused = NOT_PAUSED;\\n }\\n\\n /// @notice For native unwrapping\\n receive() external payable {}\\n\\n /// @notice Processes the route generated off-chain. Has a lock\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @param to Where to transfer output tokens\\n /// @param route Route to process\\n /// @return amountOut Actual amount of the output token\\n function processRoute(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function transferValueAndprocessRoute(\\n address transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n transferValueTo.transferNative(amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value of input tokens to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueInput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n \\n /// @notice processes the route and sends amount of output token to \\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueOutput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\\n }\\n\\n /// @notice Processes the route generated off-chain\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteInternal(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) private returns (uint256 amountOut) {\\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\\n\\n uint256 realAmountIn = amountIn;\\n {\\n uint256 step = 0;\\n uint256 stream = InputStream.createStream(route);\\n while (stream.isNotEmpty()) {\\n uint8 commandCode = stream.readUint8();\\n if (commandCode == 1) {\\n uint256 usedAmount = processMyERC20(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 2) processUserERC20(stream, amountIn);\\n else if (commandCode == 3) {\\n uint256 usedAmount = processNative(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 4) processOnePool(stream);\\n else if (commandCode == 5) processInsideBento(stream);\\n else if (commandCode == 6) applyPermit(tokenIn, stream);\\n else revert('RouteProcessor: Unknown command code');\\n ++step;\\n }\\n }\\n\\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\\n if (tokenIn != Utils.NATIVE_ADDRESS)\\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\\n \\n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\\n\\n amountOut = balanceOutFinal - balanceOutInitial;\\n\\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\\n }\\n\\n /// @notice Applies ERC-2612 permit\\n /// @param tokenIn permitted token\\n /// @param stream Streamed program\\n function applyPermit(address tokenIn, uint256 stream) private {\\n uint256 value = stream.readUint();\\n uint256 deadline = stream.readUint();\\n uint8 v = stream.readUint8();\\n bytes32 r = stream.readBytes32();\\n bytes32 s = stream.readBytes32();\\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\\n }\\n }\\n\\n /// @notice Processes native coin: call swap for all pools that swap from native coin\\n /// @param stream Streamed program\\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\\n amountTotal = address(this).balance;\\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token from this contract balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\\n address token = stream.readAddress();\\n amountTotal = IERC20(token).balanceOf(address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n \\n /// @notice Processes ERC20 token from msg.sender balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n /// @param amountTotal Amount of tokens to take from msg.sender\\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\\n address token = stream.readAddress();\\n distributeAndSwap(stream, msg.sender, token, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token for cases when the token has only one output pool\\n /// @notice In this case liquidity is already at pool balance. This is an optimization\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processOnePool(uint256 stream) private {\\n address token = stream.readAddress();\\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\\n }\\n\\n /// @notice Processes Bento tokens \\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processInsideBento(uint256 stream) private {\\n address token = stream.readAddress();\\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n\\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountTotal Total amount of tokenIn for swaps \\n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\\n uint8 num = stream.readUint8();\\n unchecked {\\n for (uint256 i = 0; i < num; ++i) {\\n uint16 share = stream.readUint16();\\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\\n amountTotal -= amount;\\n swap(stream, from, tokenIn, amount);\\n }\\n }\\n }\\n\\n /// @notice Makes swap\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 poolType = stream.readUint8();\\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\\n else revert('RouteProcessor: Unknown pool type');\\n }\\n\\n /// @notice Wraps/unwraps native token\\n /// @param stream [direction & fake, recipient, wrapToken?]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 directionAndFake = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (directionAndFake & 1 == 1) { // wrap native\\n address wrapToken = stream.readAddress();\\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\\n } else { // unwrap native\\n if (directionAndFake & 2 == 0) {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IWETH(tokenIn).withdraw(amountIn);\\n }\\n to.transferNative(amountIn);\\n }\\n }\\n\\n /// @notice Bridge/unbridge tokens to/from Bento\\n /// @param stream [direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (direction > 0) { // outside to Bento\\n // deposit to arbitrary recipient is possible only from address(bentoBox)\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\\n else {\\n // tokens already are at address(bentoBox)\\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\\n bentoBox.strategyData(tokenIn).balance -\\n bentoBox.totals(tokenIn).elastic;\\n }\\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\\n } else { // Bento to outside\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\\n }\\n }\\n\\n /// @notice UniswapV2 pool swap\\n /// @param stream [pool, direction, recipient, fee]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\\n\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\\n\\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\\n\\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\\n }\\n\\n /// @notice Trident pool swap\\n /// @param stream [pool, swapData]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bytes memory swapData = stream.readBytes();\\n\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, pool, amountIn);\\n }\\n \\n IPool(pool).swap(swapData);\\n }\\n\\n /// @notice UniswapV3 pool swap\\n /// @param stream [pool, direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bool zeroForOne = stream.readUint8() > 0;\\n address recipient = stream.readAddress();\\n\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\\n\\n lastCalledPool = pool;\\n IUniswapV3Pool(pool).swap(\\n recipient,\\n zeroForOne,\\n int256(amountIn),\\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\\n abi.encode(tokenIn)\\n );\\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) public {\\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\\n \\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n (address tokenIn) = abi.decode(data, (address));\\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\\n function algebraSwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\\n function pancakeV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 poolType = stream.readUint8();\\n int128 fromIndex = int8(stream.readUint8());\\n int128 toIndex = int8(stream.readUint8());\\n address to = stream.readAddress();\\n address tokenOut = stream.readAddress();\\n\\n uint256 amountOut;\\n if (tokenIn == Utils.NATIVE_ADDRESS) {\\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\\n } else {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IERC20(tokenIn).approveSafe(pool, amountIn);\\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n else {\\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\\n amountOut = balanceAfter - balanceBefore;\\n }\\n }\\n\\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\\n }\\n}\\n\",\"keccak256\":\"0xcd53a7f473f1847d44c42777a194203cbff02b8c761cb2935402401f57c918a2\",\"license\":\"UNLICENSED\"},\"contracts/Utils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\n\\nlibrary Utils {\\n using SafeERC20 for IERC20;\\n\\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n /**\\n * @dev returns user's balance of token (or native)\\n */\\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\\n if (token == NATIVE_ADDRESS) return address(user).balance;\\n else return IERC20(token).balanceOf(user);\\n }\\n\\n /**\\n * @dev transfers native with correct revert bubble up\\n */\\n function transferNative(address to, uint256 amount) internal {\\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\\n if (!success) {\\n assembly {\\n revert(add(32, returnBytes), mload(returnBytes))\\n }\\n }\\n }\\n\\n /**\\n * @dev transfers ERC20 or native\\n */\\n function transferAny(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\\n else IERC20(token).safeTransfer(to, amount);\\n }\\n\\n /**\\n * @dev transfers from ERC20 or transfers native\\n */\\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n (bool success, bytes memory data) = address(token).call(\\n abi.encodeWithSelector(token.approve.selector, spender, amount)\\n );\\n return success && (data.length == 0 || abi.decode(data, (bool)));\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \\n * current allowance are not zero simultaniously (USDT for example). \\n * In second case it tries to set allowance to 0, and then back to amount.\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n return approveStable(token, spender, amount) \\n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\\n }\\n}\\n\",\"keccak256\":\"0x8c8439edc00b403abd3f34be75a06b1fe71152644ae9f19488af596bbc534ffe\",\"license\":\"UNLICENSED\"},\"interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\nstruct StrategyData {\\n uint64 strategyStartDate;\\n uint64 targetPercentage;\\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n function strategyData(address token) external view returns (StrategyData memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0x0c12eba7a5b9d22d37ab8883fe22d6a312a90682809dbd11c43f8e6ceaff73bf\",\"license\":\"UNLICENSED\"},\"interfaces/ICurve.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\ninterface ICurve {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\\n}\\n\\ninterface ICurveLegacy {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\\n}\\n\\n\",\"keccak256\":\"0x3d4940b3583e06dde20f12e92d2f6ac573b3f64bdaa1e8f480656a3763852518\",\"license\":\"UNLICENSED\"},\"interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/ITridentCLPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface ITridentCLPool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bool unwrapBento,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x572376b80c86a94692b0e27e6e63790b763295e32ba1f956c1d331fc1296de8d\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IUniswapV2Pair.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Pair {\\n event Approval(address indexed owner, address indexed spender, uint value);\\n event Transfer(address indexed from, address indexed to, uint value);\\n\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function allowance(address owner, address spender) external view returns (uint);\\n\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address to, uint value) external returns (bool);\\n function transferFrom(address from, address to, uint value) external returns (bool);\\n\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n function nonces(address owner) external view returns (uint);\\n\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n event Mint(address indexed sender, uint amount0, uint amount1);\\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\\n event Swap(\\n address indexed sender,\\n uint amount0In,\\n uint amount1In,\\n uint amount0Out,\\n uint amount1Out,\\n address indexed to\\n );\\n event Sync(uint112 reserve0, uint112 reserve1);\\n\\n function MINIMUM_LIQUIDITY() external pure returns (uint);\\n function factory() external view returns (address);\\n function token0() external view returns (address);\\n function token1() external view returns (address);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\\n function price0CumulativeLast() external view returns (uint);\\n function price1CumulativeLast() external view returns (uint);\\n function kLast() external view returns (uint);\\n\\n function mint(address to) external returns (uint liquidity);\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function skim(address to) external;\\n function sync() external;\\n\\n function initialize(address, address) external;\\n}\",\"keccak256\":\"0x08f9a63b34855eec941be8d36a04424f1a1725a2c030373fcef3afeb480ca385\",\"license\":\"GPL-3.0\"},\"interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IUniswapV3Pool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x2a4d7c6120e613f0e95d4dc8c650efb9b59e3c25c64e3e5c0a379281500f0a79\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IWETH.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0xae8529ae159f784b90fdcd0629bd03bf7b68accc81edccac53357ad08406a378\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}", + "bytecode": "0x60a06040526002805461ffff60a01b191661010160a01b1790553480156200002657600080fd5b50604051620040a3380380620040a383398101604081905262000049916200016e565b6200005433620000eb565b6001600160a01b038216608052600280546001600160a01b031916600117905560005b8151811015620000e25760018060008484815181106200009b576200009b62000257565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000d9816200026d565b91505062000077565b50505062000297565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200015357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200018257600080fd5b6200018d836200013b565b602084810151919350906001600160401b0380821115620001ad57600080fd5b818601915086601f830112620001c257600080fd5b815181811115620001d757620001d762000158565b8060051b604051601f19603f83011681018181108582111715620001ff57620001ff62000158565b6040529182528482019250838101850191898311156200021e57600080fd5b938501935b82851015620002475762000237856200013b565b8452938501939285019262000223565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200029057634e487b7160e01b600052601160045260246000fd5b5060010190565b608051613da3620003006000396000818161018d01528181611798015281816127380152818161279d01528181612807015281816128cc0152818161297901528181612a5d01528181612b6401528181612c1001528181612cdf0152612df10152613da36000f3fe6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "deployedBytecode": "0x6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "devdoc": { + "author": "Ilya Lyalin", + "kind": "dev", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IAlgebraPoolActions#swap call" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the PancakeV3Pool#swap call" + } + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "route": "Route to process", + "to": "Where to transfer output tokens", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IUniswapV3PoolActions#swap call" + } + } + }, + "title": "A route processor for the Sushi Aggregator", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IAlgebraPool#swap." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via PancakeV3Pool#swap." + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "notice": "Processes the route generated off-chain. Has a lock" + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value of input tokens to and then processes the route" + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "processes the route and sends amount of output token to " + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value to and then processes the route" + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 1060, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "priviledgedUsers", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 1062, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "lastCalledPool", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 1065, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "unlocked", + "offset": 20, + "slot": "2", + "type": "t_uint8" + }, + { + "astId": 1068, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "paused", + "offset": 21, + "slot": "2", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/arbitrum-nova/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json b/protocols/route-processor/deployments/arbitrum-nova/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json new file mode 100644 index 0000000000..01826e7b93 --- /dev/null +++ b/protocols/route-processor/deployments/arbitrum-nova/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json @@ -0,0 +1,80 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" + }, + "contracts/InputStream.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" + }, + "contracts/RouteProcessor5.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" + }, + "contracts/Utils.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "interfaces/IBentoBoxMinimal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" + }, + "interfaces/ICurve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" + }, + "interfaces/IPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" + }, + "interfaces/ITridentCLPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/arbitrum/RouteProcessor5.json b/protocols/route-processor/deployments/arbitrum/RouteProcessor5.json new file mode 100644 index 0000000000..83e3201df3 --- /dev/null +++ b/protocols/route-processor/deployments/arbitrum/RouteProcessor5.json @@ -0,0 +1,704 @@ +{ + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_bentoBox", + "type": "address" + }, + { + "internalType": "address[]", + "name": "priviledgedUserList", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "MinimalOutputBalanceViolation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Route", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "algebraSwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bentoBox", + "outputs": [ + { + "internalType": "contract IBentoBoxMinimal", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "pancakeV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "priviledgedUsers", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueInput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "priviledge", + "type": "bool" + } + ], + "name": "setPriviledge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "transferValueAndprocessRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x354140ba217746c9ccf8a9b2879b61b7cba1324cad2402eba045a776dd2f6ec6", + "receipt": { + "to": null, + "from": "0x282607716D9B4fDD0B094d5864fac56313f5e665", + "contractAddress": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "transactionIndex": 11, + "gasUsed": "3813724", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000020000000000000000000000000000000000000001000000000000000000000000000000000000000000040000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000000000000000000000000000", + "blockHash": "0x57b73a495aab6716a1243a2cc8b85c9c247d7e1e05e42b5454d75a28afa1db4e", + "transactionHash": "0x354140ba217746c9ccf8a9b2879b61b7cba1324cad2402eba045a776dd2f6ec6", + "logs": [ + { + "transactionIndex": 11, + "blockNumber": 237200605, + "transactionHash": "0x354140ba217746c9ccf8a9b2879b61b7cba1324cad2402eba045a776dd2f6ec6", + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000282607716d9b4fdd0b094d5864fac56313f5e665" + ], + "data": "0x", + "logIndex": 21, + "blockHash": "0x57b73a495aab6716a1243a2cc8b85c9c247d7e1e05e42b5454d75a28afa1db4e" + } + ], + "blockNumber": 237200605, + "cumulativeGasUsed": "5838787", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000000", + [] + ], + "numDeployments": 1, + "solcInputHash": "e556d43a3caf4f1fb4f12d632d103b28", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bentoBox\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"priviledgedUserList\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"MinimalOutputBalanceViolation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"Route\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"algebraSwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"pancakeV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"priviledgedUsers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"priviledge\",\"type\":\"bool\"}],\"name\":\"setPriviledge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"transferValueAndprocessRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"Ilya Lyalin\",\"kind\":\"dev\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IAlgebraPoolActions#swap call\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the PancakeV3Pool#swap call\"}},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"route\":\"Route to process\",\"to\":\"Where to transfer output tokens\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IUniswapV3PoolActions#swap call\"}}},\"title\":\"A route processor for the Sushi Aggregator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\"},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Processes the route generated off-chain. Has a lock\"},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value of input tokens to and then processes the route\"},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"processes the route and sends amount of output token to \"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value to and then processes the route\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RouteProcessor5.sol\":\"RouteProcessor5\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\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 Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.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 function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\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\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\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 * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\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\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/InputStream.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\n/** @notice Simple read stream */\\nlibrary InputStream {\\n\\n /** @notice Creates stream from data\\n * @param data data\\n */\\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\\n assembly {\\n stream := mload(0x40)\\n mstore(0x40, add(stream, 64))\\n mstore(stream, data)\\n let length := mload(data)\\n mstore(add(stream, 32), add(data, length))\\n }\\n }\\n\\n /** @notice Checks if stream is not empty\\n * @param stream stream\\n */\\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\\n uint256 pos;\\n uint256 finish;\\n assembly {\\n pos := mload(stream)\\n finish := mload(add(stream, 32))\\n }\\n return pos < finish;\\n }\\n\\n /** @notice Reads uint8 from the stream\\n * @param stream stream\\n */\\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 1)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint16 from the stream\\n * @param stream stream\\n */\\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 2)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint24 from the stream\\n * @param stream stream\\n */\\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 3)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint32 from the stream\\n * @param stream stream\\n */\\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 4)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint256 from the stream\\n * @param stream stream\\n */\\n function readUint(uint256 stream) internal pure returns (uint256 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes32 from the stream\\n * @param stream stream\\n */\\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads address from the stream\\n * @param stream stream\\n */\\n function readAddress(uint256 stream) internal pure returns (address res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 20)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes from the stream\\n * @param stream stream\\n */\\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\\n assembly {\\n let pos := mload(stream)\\n res := add(pos, 32)\\n let length := mload(res)\\n mstore(stream, add(res, length))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x24e24bd0e49cbddacbf3b26bcd4bdffac63d11f3259bc05bc93c0835e8ff5300\",\"license\":\"UNLICENSED\"},\"contracts/RouteProcessor5.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '../interfaces/IUniswapV2Pair.sol';\\nimport '../interfaces/IUniswapV3Pool.sol';\\nimport '../interfaces/ITridentCLPool.sol';\\nimport '../interfaces/IBentoBoxMinimal.sol';\\nimport '../interfaces/IPool.sol';\\nimport '../interfaces/IWETH.sol';\\nimport '../interfaces/ICurve.sol';\\nimport './InputStream.sol';\\nimport './Utils.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\\n\\nuint8 constant LOCKED = 2;\\nuint8 constant NOT_LOCKED = 1;\\nuint8 constant PAUSED = 2;\\nuint8 constant NOT_PAUSED = 1;\\n\\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\nuint160 constant MIN_SQRT_RATIO = 4295128739;\\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n/// @title A route processor for the Sushi Aggregator\\n/// @author Ilya Lyalin\\ncontract RouteProcessor5 is Ownable {\\n using SafeERC20 for IERC20;\\n using Utils for IERC20;\\n using Utils for address;\\n using SafeERC20 for IERC20Permit;\\n using InputStream for uint256;\\n\\n event Route(\\n address indexed from, \\n address to, \\n address indexed tokenIn, \\n address indexed tokenOut, \\n uint256 amountIn, \\n uint256 amountOutMin,\\n uint256 amountOut\\n );\\n\\n error MinimalOutputBalanceViolation(uint256 amountOut);\\n\\n IBentoBoxMinimal public immutable bentoBox;\\n mapping (address => bool) public priviledgedUsers;\\n address private lastCalledPool;\\n\\n uint8 private unlocked = NOT_LOCKED;\\n uint8 private paused = NOT_PAUSED;\\n modifier lock() {\\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\\n unlocked = LOCKED;\\n _;\\n unlocked = NOT_LOCKED;\\n }\\n\\n modifier onlyOwnerOrPriviledgedUser() {\\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \\\"RP: caller is not the owner or a privileged user\\\");\\n _;\\n }\\n\\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\\n bentoBox = IBentoBoxMinimal(_bentoBox);\\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n\\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\\n priviledgedUsers[priviledgedUserList[i]] = true;\\n }\\n }\\n\\n function setPriviledge(address user, bool priviledge) external onlyOwner {\\n priviledgedUsers[user] = priviledge;\\n }\\n\\n function pause() external onlyOwnerOrPriviledgedUser {\\n paused = PAUSED;\\n }\\n\\n function resume() external onlyOwnerOrPriviledgedUser {\\n paused = NOT_PAUSED;\\n }\\n\\n /// @notice For native unwrapping\\n receive() external payable {}\\n\\n /// @notice Processes the route generated off-chain. Has a lock\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @param to Where to transfer output tokens\\n /// @param route Route to process\\n /// @return amountOut Actual amount of the output token\\n function processRoute(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function transferValueAndprocessRoute(\\n address transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n transferValueTo.transferNative(amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value of input tokens to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueInput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n \\n /// @notice processes the route and sends amount of output token to \\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueOutput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\\n }\\n\\n /// @notice Processes the route generated off-chain\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteInternal(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) private returns (uint256 amountOut) {\\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\\n\\n uint256 realAmountIn = amountIn;\\n {\\n uint256 step = 0;\\n uint256 stream = InputStream.createStream(route);\\n while (stream.isNotEmpty()) {\\n uint8 commandCode = stream.readUint8();\\n if (commandCode == 1) {\\n uint256 usedAmount = processMyERC20(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 2) processUserERC20(stream, amountIn);\\n else if (commandCode == 3) {\\n uint256 usedAmount = processNative(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 4) processOnePool(stream);\\n else if (commandCode == 5) processInsideBento(stream);\\n else if (commandCode == 6) applyPermit(tokenIn, stream);\\n else revert('RouteProcessor: Unknown command code');\\n ++step;\\n }\\n }\\n\\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\\n if (tokenIn != Utils.NATIVE_ADDRESS)\\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\\n \\n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\\n\\n amountOut = balanceOutFinal - balanceOutInitial;\\n\\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\\n }\\n\\n /// @notice Applies ERC-2612 permit\\n /// @param tokenIn permitted token\\n /// @param stream Streamed program\\n function applyPermit(address tokenIn, uint256 stream) private {\\n uint256 value = stream.readUint();\\n uint256 deadline = stream.readUint();\\n uint8 v = stream.readUint8();\\n bytes32 r = stream.readBytes32();\\n bytes32 s = stream.readBytes32();\\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\\n }\\n }\\n\\n /// @notice Processes native coin: call swap for all pools that swap from native coin\\n /// @param stream Streamed program\\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\\n amountTotal = address(this).balance;\\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token from this contract balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\\n address token = stream.readAddress();\\n amountTotal = IERC20(token).balanceOf(address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n \\n /// @notice Processes ERC20 token from msg.sender balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n /// @param amountTotal Amount of tokens to take from msg.sender\\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\\n address token = stream.readAddress();\\n distributeAndSwap(stream, msg.sender, token, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token for cases when the token has only one output pool\\n /// @notice In this case liquidity is already at pool balance. This is an optimization\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processOnePool(uint256 stream) private {\\n address token = stream.readAddress();\\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\\n }\\n\\n /// @notice Processes Bento tokens \\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processInsideBento(uint256 stream) private {\\n address token = stream.readAddress();\\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n\\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountTotal Total amount of tokenIn for swaps \\n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\\n uint8 num = stream.readUint8();\\n unchecked {\\n for (uint256 i = 0; i < num; ++i) {\\n uint16 share = stream.readUint16();\\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\\n amountTotal -= amount;\\n swap(stream, from, tokenIn, amount);\\n }\\n }\\n }\\n\\n /// @notice Makes swap\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 poolType = stream.readUint8();\\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\\n else revert('RouteProcessor: Unknown pool type');\\n }\\n\\n /// @notice Wraps/unwraps native token\\n /// @param stream [direction & fake, recipient, wrapToken?]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 directionAndFake = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (directionAndFake & 1 == 1) { // wrap native\\n address wrapToken = stream.readAddress();\\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\\n } else { // unwrap native\\n if (directionAndFake & 2 == 0) {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IWETH(tokenIn).withdraw(amountIn);\\n }\\n to.transferNative(amountIn);\\n }\\n }\\n\\n /// @notice Bridge/unbridge tokens to/from Bento\\n /// @param stream [direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (direction > 0) { // outside to Bento\\n // deposit to arbitrary recipient is possible only from address(bentoBox)\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\\n else {\\n // tokens already are at address(bentoBox)\\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\\n bentoBox.strategyData(tokenIn).balance -\\n bentoBox.totals(tokenIn).elastic;\\n }\\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\\n } else { // Bento to outside\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\\n }\\n }\\n\\n /// @notice UniswapV2 pool swap\\n /// @param stream [pool, direction, recipient, fee]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\\n\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\\n\\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\\n\\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\\n }\\n\\n /// @notice Trident pool swap\\n /// @param stream [pool, swapData]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bytes memory swapData = stream.readBytes();\\n\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, pool, amountIn);\\n }\\n \\n IPool(pool).swap(swapData);\\n }\\n\\n /// @notice UniswapV3 pool swap\\n /// @param stream [pool, direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bool zeroForOne = stream.readUint8() > 0;\\n address recipient = stream.readAddress();\\n\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\\n\\n lastCalledPool = pool;\\n IUniswapV3Pool(pool).swap(\\n recipient,\\n zeroForOne,\\n int256(amountIn),\\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\\n abi.encode(tokenIn)\\n );\\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) public {\\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\\n \\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n (address tokenIn) = abi.decode(data, (address));\\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\\n function algebraSwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\\n function pancakeV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 poolType = stream.readUint8();\\n int128 fromIndex = int8(stream.readUint8());\\n int128 toIndex = int8(stream.readUint8());\\n address to = stream.readAddress();\\n address tokenOut = stream.readAddress();\\n\\n uint256 amountOut;\\n if (tokenIn == Utils.NATIVE_ADDRESS) {\\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\\n } else {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IERC20(tokenIn).approveSafe(pool, amountIn);\\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n else {\\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\\n amountOut = balanceAfter - balanceBefore;\\n }\\n }\\n\\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\\n }\\n}\\n\",\"keccak256\":\"0xcd53a7f473f1847d44c42777a194203cbff02b8c761cb2935402401f57c918a2\",\"license\":\"UNLICENSED\"},\"contracts/Utils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\n\\nlibrary Utils {\\n using SafeERC20 for IERC20;\\n\\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n /**\\n * @dev returns user's balance of token (or native)\\n */\\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\\n if (token == NATIVE_ADDRESS) return address(user).balance;\\n else return IERC20(token).balanceOf(user);\\n }\\n\\n /**\\n * @dev transfers native with correct revert bubble up\\n */\\n function transferNative(address to, uint256 amount) internal {\\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\\n if (!success) {\\n assembly {\\n revert(add(32, returnBytes), mload(returnBytes))\\n }\\n }\\n }\\n\\n /**\\n * @dev transfers ERC20 or native\\n */\\n function transferAny(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\\n else IERC20(token).safeTransfer(to, amount);\\n }\\n\\n /**\\n * @dev transfers from ERC20 or transfers native\\n */\\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n (bool success, bytes memory data) = address(token).call(\\n abi.encodeWithSelector(token.approve.selector, spender, amount)\\n );\\n return success && (data.length == 0 || abi.decode(data, (bool)));\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \\n * current allowance are not zero simultaniously (USDT for example). \\n * In second case it tries to set allowance to 0, and then back to amount.\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n return approveStable(token, spender, amount) \\n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\\n }\\n}\\n\",\"keccak256\":\"0x8c8439edc00b403abd3f34be75a06b1fe71152644ae9f19488af596bbc534ffe\",\"license\":\"UNLICENSED\"},\"interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\nstruct StrategyData {\\n uint64 strategyStartDate;\\n uint64 targetPercentage;\\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n function strategyData(address token) external view returns (StrategyData memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0x0c12eba7a5b9d22d37ab8883fe22d6a312a90682809dbd11c43f8e6ceaff73bf\",\"license\":\"UNLICENSED\"},\"interfaces/ICurve.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\ninterface ICurve {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\\n}\\n\\ninterface ICurveLegacy {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\\n}\\n\\n\",\"keccak256\":\"0x3d4940b3583e06dde20f12e92d2f6ac573b3f64bdaa1e8f480656a3763852518\",\"license\":\"UNLICENSED\"},\"interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/ITridentCLPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface ITridentCLPool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bool unwrapBento,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x572376b80c86a94692b0e27e6e63790b763295e32ba1f956c1d331fc1296de8d\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IUniswapV2Pair.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Pair {\\n event Approval(address indexed owner, address indexed spender, uint value);\\n event Transfer(address indexed from, address indexed to, uint value);\\n\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function allowance(address owner, address spender) external view returns (uint);\\n\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address to, uint value) external returns (bool);\\n function transferFrom(address from, address to, uint value) external returns (bool);\\n\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n function nonces(address owner) external view returns (uint);\\n\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n event Mint(address indexed sender, uint amount0, uint amount1);\\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\\n event Swap(\\n address indexed sender,\\n uint amount0In,\\n uint amount1In,\\n uint amount0Out,\\n uint amount1Out,\\n address indexed to\\n );\\n event Sync(uint112 reserve0, uint112 reserve1);\\n\\n function MINIMUM_LIQUIDITY() external pure returns (uint);\\n function factory() external view returns (address);\\n function token0() external view returns (address);\\n function token1() external view returns (address);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\\n function price0CumulativeLast() external view returns (uint);\\n function price1CumulativeLast() external view returns (uint);\\n function kLast() external view returns (uint);\\n\\n function mint(address to) external returns (uint liquidity);\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function skim(address to) external;\\n function sync() external;\\n\\n function initialize(address, address) external;\\n}\",\"keccak256\":\"0x08f9a63b34855eec941be8d36a04424f1a1725a2c030373fcef3afeb480ca385\",\"license\":\"GPL-3.0\"},\"interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IUniswapV3Pool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x2a4d7c6120e613f0e95d4dc8c650efb9b59e3c25c64e3e5c0a379281500f0a79\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IWETH.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0xae8529ae159f784b90fdcd0629bd03bf7b68accc81edccac53357ad08406a378\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}", + "bytecode": "0x60a06040526002805461ffff60a01b191661010160a01b1790553480156200002657600080fd5b50604051620040a3380380620040a383398101604081905262000049916200016e565b6200005433620000eb565b6001600160a01b038216608052600280546001600160a01b031916600117905560005b8151811015620000e25760018060008484815181106200009b576200009b62000257565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000d9816200026d565b91505062000077565b50505062000297565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200015357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200018257600080fd5b6200018d836200013b565b602084810151919350906001600160401b0380821115620001ad57600080fd5b818601915086601f830112620001c257600080fd5b815181811115620001d757620001d762000158565b8060051b604051601f19603f83011681018181108582111715620001ff57620001ff62000158565b6040529182528482019250838101850191898311156200021e57600080fd5b938501935b82851015620002475762000237856200013b565b8452938501939285019262000223565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200029057634e487b7160e01b600052601160045260246000fd5b5060010190565b608051613da3620003006000396000818161018d01528181611798015281816127380152818161279d01528181612807015281816128cc0152818161297901528181612a5d01528181612b6401528181612c1001528181612cdf0152612df10152613da36000f3fe6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "deployedBytecode": "0x6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "devdoc": { + "author": "Ilya Lyalin", + "kind": "dev", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IAlgebraPoolActions#swap call" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the PancakeV3Pool#swap call" + } + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "route": "Route to process", + "to": "Where to transfer output tokens", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IUniswapV3PoolActions#swap call" + } + } + }, + "title": "A route processor for the Sushi Aggregator", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IAlgebraPool#swap." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via PancakeV3Pool#swap." + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "notice": "Processes the route generated off-chain. Has a lock" + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value of input tokens to and then processes the route" + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "processes the route and sends amount of output token to " + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value to and then processes the route" + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 1060, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "priviledgedUsers", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 1062, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "lastCalledPool", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 1065, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "unlocked", + "offset": 20, + "slot": "2", + "type": "t_uint8" + }, + { + "astId": 1068, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "paused", + "offset": 21, + "slot": "2", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/arbitrum/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json b/protocols/route-processor/deployments/arbitrum/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json new file mode 100644 index 0000000000..01826e7b93 --- /dev/null +++ b/protocols/route-processor/deployments/arbitrum/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json @@ -0,0 +1,80 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" + }, + "contracts/InputStream.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" + }, + "contracts/RouteProcessor5.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" + }, + "contracts/Utils.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "interfaces/IBentoBoxMinimal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" + }, + "interfaces/ICurve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" + }, + "interfaces/IPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" + }, + "interfaces/ITridentCLPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/avalanche/RouteProcessor5.json b/protocols/route-processor/deployments/avalanche/RouteProcessor5.json new file mode 100644 index 0000000000..0107e57318 --- /dev/null +++ b/protocols/route-processor/deployments/avalanche/RouteProcessor5.json @@ -0,0 +1,704 @@ +{ + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_bentoBox", + "type": "address" + }, + { + "internalType": "address[]", + "name": "priviledgedUserList", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "MinimalOutputBalanceViolation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Route", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "algebraSwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bentoBox", + "outputs": [ + { + "internalType": "contract IBentoBoxMinimal", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "pancakeV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "priviledgedUsers", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueInput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "priviledge", + "type": "bool" + } + ], + "name": "setPriviledge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "transferValueAndprocessRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x0b961084d1f7a5a9c4774371c8c4ea8792db430238d62fcbbd5a26794b9e89bb", + "receipt": { + "to": null, + "from": "0x282607716D9B4fDD0B094d5864fac56313f5e665", + "contractAddress": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "transactionIndex": 2, + "gasUsed": "3489875", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000020000000000000000000000000000000000000001000000000000000000000000000000000000000000040000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000000000000000000000000000", + "blockHash": "0x091eac0cd636a855fbac4f5db496395882a2df8b2c5c1cb69d75715cab8a2938", + "transactionHash": "0x0b961084d1f7a5a9c4774371c8c4ea8792db430238d62fcbbd5a26794b9e89bb", + "logs": [ + { + "transactionIndex": 2, + "blockNumber": 48575579, + "transactionHash": "0x0b961084d1f7a5a9c4774371c8c4ea8792db430238d62fcbbd5a26794b9e89bb", + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000282607716d9b4fdd0b094d5864fac56313f5e665" + ], + "data": "0x", + "logIndex": 5, + "blockHash": "0x091eac0cd636a855fbac4f5db496395882a2df8b2c5c1cb69d75715cab8a2938" + } + ], + "blockNumber": 48575579, + "cumulativeGasUsed": "3717005", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000000", + [] + ], + "numDeployments": 1, + "solcInputHash": "e556d43a3caf4f1fb4f12d632d103b28", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bentoBox\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"priviledgedUserList\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"MinimalOutputBalanceViolation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"Route\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"algebraSwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"pancakeV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"priviledgedUsers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"priviledge\",\"type\":\"bool\"}],\"name\":\"setPriviledge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"transferValueAndprocessRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"Ilya Lyalin\",\"kind\":\"dev\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IAlgebraPoolActions#swap call\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the PancakeV3Pool#swap call\"}},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"route\":\"Route to process\",\"to\":\"Where to transfer output tokens\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IUniswapV3PoolActions#swap call\"}}},\"title\":\"A route processor for the Sushi Aggregator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\"},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Processes the route generated off-chain. Has a lock\"},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value of input tokens to and then processes the route\"},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"processes the route and sends amount of output token to \"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value to and then processes the route\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RouteProcessor5.sol\":\"RouteProcessor5\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\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 Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.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 function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\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\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\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 * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\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\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/InputStream.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\n/** @notice Simple read stream */\\nlibrary InputStream {\\n\\n /** @notice Creates stream from data\\n * @param data data\\n */\\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\\n assembly {\\n stream := mload(0x40)\\n mstore(0x40, add(stream, 64))\\n mstore(stream, data)\\n let length := mload(data)\\n mstore(add(stream, 32), add(data, length))\\n }\\n }\\n\\n /** @notice Checks if stream is not empty\\n * @param stream stream\\n */\\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\\n uint256 pos;\\n uint256 finish;\\n assembly {\\n pos := mload(stream)\\n finish := mload(add(stream, 32))\\n }\\n return pos < finish;\\n }\\n\\n /** @notice Reads uint8 from the stream\\n * @param stream stream\\n */\\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 1)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint16 from the stream\\n * @param stream stream\\n */\\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 2)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint24 from the stream\\n * @param stream stream\\n */\\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 3)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint32 from the stream\\n * @param stream stream\\n */\\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 4)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint256 from the stream\\n * @param stream stream\\n */\\n function readUint(uint256 stream) internal pure returns (uint256 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes32 from the stream\\n * @param stream stream\\n */\\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads address from the stream\\n * @param stream stream\\n */\\n function readAddress(uint256 stream) internal pure returns (address res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 20)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes from the stream\\n * @param stream stream\\n */\\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\\n assembly {\\n let pos := mload(stream)\\n res := add(pos, 32)\\n let length := mload(res)\\n mstore(stream, add(res, length))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x24e24bd0e49cbddacbf3b26bcd4bdffac63d11f3259bc05bc93c0835e8ff5300\",\"license\":\"UNLICENSED\"},\"contracts/RouteProcessor5.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '../interfaces/IUniswapV2Pair.sol';\\nimport '../interfaces/IUniswapV3Pool.sol';\\nimport '../interfaces/ITridentCLPool.sol';\\nimport '../interfaces/IBentoBoxMinimal.sol';\\nimport '../interfaces/IPool.sol';\\nimport '../interfaces/IWETH.sol';\\nimport '../interfaces/ICurve.sol';\\nimport './InputStream.sol';\\nimport './Utils.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\\n\\nuint8 constant LOCKED = 2;\\nuint8 constant NOT_LOCKED = 1;\\nuint8 constant PAUSED = 2;\\nuint8 constant NOT_PAUSED = 1;\\n\\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\nuint160 constant MIN_SQRT_RATIO = 4295128739;\\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n/// @title A route processor for the Sushi Aggregator\\n/// @author Ilya Lyalin\\ncontract RouteProcessor5 is Ownable {\\n using SafeERC20 for IERC20;\\n using Utils for IERC20;\\n using Utils for address;\\n using SafeERC20 for IERC20Permit;\\n using InputStream for uint256;\\n\\n event Route(\\n address indexed from, \\n address to, \\n address indexed tokenIn, \\n address indexed tokenOut, \\n uint256 amountIn, \\n uint256 amountOutMin,\\n uint256 amountOut\\n );\\n\\n error MinimalOutputBalanceViolation(uint256 amountOut);\\n\\n IBentoBoxMinimal public immutable bentoBox;\\n mapping (address => bool) public priviledgedUsers;\\n address private lastCalledPool;\\n\\n uint8 private unlocked = NOT_LOCKED;\\n uint8 private paused = NOT_PAUSED;\\n modifier lock() {\\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\\n unlocked = LOCKED;\\n _;\\n unlocked = NOT_LOCKED;\\n }\\n\\n modifier onlyOwnerOrPriviledgedUser() {\\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \\\"RP: caller is not the owner or a privileged user\\\");\\n _;\\n }\\n\\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\\n bentoBox = IBentoBoxMinimal(_bentoBox);\\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n\\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\\n priviledgedUsers[priviledgedUserList[i]] = true;\\n }\\n }\\n\\n function setPriviledge(address user, bool priviledge) external onlyOwner {\\n priviledgedUsers[user] = priviledge;\\n }\\n\\n function pause() external onlyOwnerOrPriviledgedUser {\\n paused = PAUSED;\\n }\\n\\n function resume() external onlyOwnerOrPriviledgedUser {\\n paused = NOT_PAUSED;\\n }\\n\\n /// @notice For native unwrapping\\n receive() external payable {}\\n\\n /// @notice Processes the route generated off-chain. Has a lock\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @param to Where to transfer output tokens\\n /// @param route Route to process\\n /// @return amountOut Actual amount of the output token\\n function processRoute(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function transferValueAndprocessRoute(\\n address transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n transferValueTo.transferNative(amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value of input tokens to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueInput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n \\n /// @notice processes the route and sends amount of output token to \\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueOutput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\\n }\\n\\n /// @notice Processes the route generated off-chain\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteInternal(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) private returns (uint256 amountOut) {\\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\\n\\n uint256 realAmountIn = amountIn;\\n {\\n uint256 step = 0;\\n uint256 stream = InputStream.createStream(route);\\n while (stream.isNotEmpty()) {\\n uint8 commandCode = stream.readUint8();\\n if (commandCode == 1) {\\n uint256 usedAmount = processMyERC20(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 2) processUserERC20(stream, amountIn);\\n else if (commandCode == 3) {\\n uint256 usedAmount = processNative(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 4) processOnePool(stream);\\n else if (commandCode == 5) processInsideBento(stream);\\n else if (commandCode == 6) applyPermit(tokenIn, stream);\\n else revert('RouteProcessor: Unknown command code');\\n ++step;\\n }\\n }\\n\\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\\n if (tokenIn != Utils.NATIVE_ADDRESS)\\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\\n \\n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\\n\\n amountOut = balanceOutFinal - balanceOutInitial;\\n\\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\\n }\\n\\n /// @notice Applies ERC-2612 permit\\n /// @param tokenIn permitted token\\n /// @param stream Streamed program\\n function applyPermit(address tokenIn, uint256 stream) private {\\n uint256 value = stream.readUint();\\n uint256 deadline = stream.readUint();\\n uint8 v = stream.readUint8();\\n bytes32 r = stream.readBytes32();\\n bytes32 s = stream.readBytes32();\\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\\n }\\n }\\n\\n /// @notice Processes native coin: call swap for all pools that swap from native coin\\n /// @param stream Streamed program\\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\\n amountTotal = address(this).balance;\\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token from this contract balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\\n address token = stream.readAddress();\\n amountTotal = IERC20(token).balanceOf(address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n \\n /// @notice Processes ERC20 token from msg.sender balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n /// @param amountTotal Amount of tokens to take from msg.sender\\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\\n address token = stream.readAddress();\\n distributeAndSwap(stream, msg.sender, token, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token for cases when the token has only one output pool\\n /// @notice In this case liquidity is already at pool balance. This is an optimization\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processOnePool(uint256 stream) private {\\n address token = stream.readAddress();\\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\\n }\\n\\n /// @notice Processes Bento tokens \\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processInsideBento(uint256 stream) private {\\n address token = stream.readAddress();\\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n\\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountTotal Total amount of tokenIn for swaps \\n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\\n uint8 num = stream.readUint8();\\n unchecked {\\n for (uint256 i = 0; i < num; ++i) {\\n uint16 share = stream.readUint16();\\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\\n amountTotal -= amount;\\n swap(stream, from, tokenIn, amount);\\n }\\n }\\n }\\n\\n /// @notice Makes swap\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 poolType = stream.readUint8();\\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\\n else revert('RouteProcessor: Unknown pool type');\\n }\\n\\n /// @notice Wraps/unwraps native token\\n /// @param stream [direction & fake, recipient, wrapToken?]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 directionAndFake = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (directionAndFake & 1 == 1) { // wrap native\\n address wrapToken = stream.readAddress();\\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\\n } else { // unwrap native\\n if (directionAndFake & 2 == 0) {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IWETH(tokenIn).withdraw(amountIn);\\n }\\n to.transferNative(amountIn);\\n }\\n }\\n\\n /// @notice Bridge/unbridge tokens to/from Bento\\n /// @param stream [direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (direction > 0) { // outside to Bento\\n // deposit to arbitrary recipient is possible only from address(bentoBox)\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\\n else {\\n // tokens already are at address(bentoBox)\\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\\n bentoBox.strategyData(tokenIn).balance -\\n bentoBox.totals(tokenIn).elastic;\\n }\\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\\n } else { // Bento to outside\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\\n }\\n }\\n\\n /// @notice UniswapV2 pool swap\\n /// @param stream [pool, direction, recipient, fee]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\\n\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\\n\\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\\n\\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\\n }\\n\\n /// @notice Trident pool swap\\n /// @param stream [pool, swapData]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bytes memory swapData = stream.readBytes();\\n\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, pool, amountIn);\\n }\\n \\n IPool(pool).swap(swapData);\\n }\\n\\n /// @notice UniswapV3 pool swap\\n /// @param stream [pool, direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bool zeroForOne = stream.readUint8() > 0;\\n address recipient = stream.readAddress();\\n\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\\n\\n lastCalledPool = pool;\\n IUniswapV3Pool(pool).swap(\\n recipient,\\n zeroForOne,\\n int256(amountIn),\\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\\n abi.encode(tokenIn)\\n );\\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) public {\\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\\n \\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n (address tokenIn) = abi.decode(data, (address));\\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\\n function algebraSwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\\n function pancakeV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 poolType = stream.readUint8();\\n int128 fromIndex = int8(stream.readUint8());\\n int128 toIndex = int8(stream.readUint8());\\n address to = stream.readAddress();\\n address tokenOut = stream.readAddress();\\n\\n uint256 amountOut;\\n if (tokenIn == Utils.NATIVE_ADDRESS) {\\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\\n } else {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IERC20(tokenIn).approveSafe(pool, amountIn);\\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n else {\\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\\n amountOut = balanceAfter - balanceBefore;\\n }\\n }\\n\\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\\n }\\n}\\n\",\"keccak256\":\"0xcd53a7f473f1847d44c42777a194203cbff02b8c761cb2935402401f57c918a2\",\"license\":\"UNLICENSED\"},\"contracts/Utils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\n\\nlibrary Utils {\\n using SafeERC20 for IERC20;\\n\\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n /**\\n * @dev returns user's balance of token (or native)\\n */\\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\\n if (token == NATIVE_ADDRESS) return address(user).balance;\\n else return IERC20(token).balanceOf(user);\\n }\\n\\n /**\\n * @dev transfers native with correct revert bubble up\\n */\\n function transferNative(address to, uint256 amount) internal {\\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\\n if (!success) {\\n assembly {\\n revert(add(32, returnBytes), mload(returnBytes))\\n }\\n }\\n }\\n\\n /**\\n * @dev transfers ERC20 or native\\n */\\n function transferAny(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\\n else IERC20(token).safeTransfer(to, amount);\\n }\\n\\n /**\\n * @dev transfers from ERC20 or transfers native\\n */\\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n (bool success, bytes memory data) = address(token).call(\\n abi.encodeWithSelector(token.approve.selector, spender, amount)\\n );\\n return success && (data.length == 0 || abi.decode(data, (bool)));\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \\n * current allowance are not zero simultaniously (USDT for example). \\n * In second case it tries to set allowance to 0, and then back to amount.\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n return approveStable(token, spender, amount) \\n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\\n }\\n}\\n\",\"keccak256\":\"0x8c8439edc00b403abd3f34be75a06b1fe71152644ae9f19488af596bbc534ffe\",\"license\":\"UNLICENSED\"},\"interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\nstruct StrategyData {\\n uint64 strategyStartDate;\\n uint64 targetPercentage;\\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n function strategyData(address token) external view returns (StrategyData memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0x0c12eba7a5b9d22d37ab8883fe22d6a312a90682809dbd11c43f8e6ceaff73bf\",\"license\":\"UNLICENSED\"},\"interfaces/ICurve.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\ninterface ICurve {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\\n}\\n\\ninterface ICurveLegacy {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\\n}\\n\\n\",\"keccak256\":\"0x3d4940b3583e06dde20f12e92d2f6ac573b3f64bdaa1e8f480656a3763852518\",\"license\":\"UNLICENSED\"},\"interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/ITridentCLPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface ITridentCLPool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bool unwrapBento,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x572376b80c86a94692b0e27e6e63790b763295e32ba1f956c1d331fc1296de8d\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IUniswapV2Pair.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Pair {\\n event Approval(address indexed owner, address indexed spender, uint value);\\n event Transfer(address indexed from, address indexed to, uint value);\\n\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function allowance(address owner, address spender) external view returns (uint);\\n\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address to, uint value) external returns (bool);\\n function transferFrom(address from, address to, uint value) external returns (bool);\\n\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n function nonces(address owner) external view returns (uint);\\n\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n event Mint(address indexed sender, uint amount0, uint amount1);\\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\\n event Swap(\\n address indexed sender,\\n uint amount0In,\\n uint amount1In,\\n uint amount0Out,\\n uint amount1Out,\\n address indexed to\\n );\\n event Sync(uint112 reserve0, uint112 reserve1);\\n\\n function MINIMUM_LIQUIDITY() external pure returns (uint);\\n function factory() external view returns (address);\\n function token0() external view returns (address);\\n function token1() external view returns (address);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\\n function price0CumulativeLast() external view returns (uint);\\n function price1CumulativeLast() external view returns (uint);\\n function kLast() external view returns (uint);\\n\\n function mint(address to) external returns (uint liquidity);\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function skim(address to) external;\\n function sync() external;\\n\\n function initialize(address, address) external;\\n}\",\"keccak256\":\"0x08f9a63b34855eec941be8d36a04424f1a1725a2c030373fcef3afeb480ca385\",\"license\":\"GPL-3.0\"},\"interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IUniswapV3Pool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x2a4d7c6120e613f0e95d4dc8c650efb9b59e3c25c64e3e5c0a379281500f0a79\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IWETH.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0xae8529ae159f784b90fdcd0629bd03bf7b68accc81edccac53357ad08406a378\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}", + "bytecode": "0x60a06040526002805461ffff60a01b191661010160a01b1790553480156200002657600080fd5b50604051620040a3380380620040a383398101604081905262000049916200016e565b6200005433620000eb565b6001600160a01b038216608052600280546001600160a01b031916600117905560005b8151811015620000e25760018060008484815181106200009b576200009b62000257565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000d9816200026d565b91505062000077565b50505062000297565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200015357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200018257600080fd5b6200018d836200013b565b602084810151919350906001600160401b0380821115620001ad57600080fd5b818601915086601f830112620001c257600080fd5b815181811115620001d757620001d762000158565b8060051b604051601f19603f83011681018181108582111715620001ff57620001ff62000158565b6040529182528482019250838101850191898311156200021e57600080fd5b938501935b82851015620002475762000237856200013b565b8452938501939285019262000223565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200029057634e487b7160e01b600052601160045260246000fd5b5060010190565b608051613da3620003006000396000818161018d01528181611798015281816127380152818161279d01528181612807015281816128cc0152818161297901528181612a5d01528181612b6401528181612c1001528181612cdf0152612df10152613da36000f3fe6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "deployedBytecode": "0x6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "devdoc": { + "author": "Ilya Lyalin", + "kind": "dev", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IAlgebraPoolActions#swap call" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the PancakeV3Pool#swap call" + } + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "route": "Route to process", + "to": "Where to transfer output tokens", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IUniswapV3PoolActions#swap call" + } + } + }, + "title": "A route processor for the Sushi Aggregator", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IAlgebraPool#swap." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via PancakeV3Pool#swap." + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "notice": "Processes the route generated off-chain. Has a lock" + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value of input tokens to and then processes the route" + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "processes the route and sends amount of output token to " + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value to and then processes the route" + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 1060, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "priviledgedUsers", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 1062, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "lastCalledPool", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 1065, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "unlocked", + "offset": 20, + "slot": "2", + "type": "t_uint8" + }, + { + "astId": 1068, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "paused", + "offset": 21, + "slot": "2", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/avalanche/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json b/protocols/route-processor/deployments/avalanche/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json new file mode 100644 index 0000000000..01826e7b93 --- /dev/null +++ b/protocols/route-processor/deployments/avalanche/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json @@ -0,0 +1,80 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" + }, + "contracts/InputStream.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" + }, + "contracts/RouteProcessor5.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" + }, + "contracts/Utils.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "interfaces/IBentoBoxMinimal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" + }, + "interfaces/ICurve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" + }, + "interfaces/IPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" + }, + "interfaces/ITridentCLPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/base/RouteProcessor5.json b/protocols/route-processor/deployments/base/RouteProcessor5.json new file mode 100644 index 0000000000..e1597fa11f --- /dev/null +++ b/protocols/route-processor/deployments/base/RouteProcessor5.json @@ -0,0 +1,704 @@ +{ + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_bentoBox", + "type": "address" + }, + { + "internalType": "address[]", + "name": "priviledgedUserList", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "MinimalOutputBalanceViolation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Route", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "algebraSwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bentoBox", + "outputs": [ + { + "internalType": "contract IBentoBoxMinimal", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "pancakeV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "priviledgedUsers", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueInput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "priviledge", + "type": "bool" + } + ], + "name": "setPriviledge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "transferValueAndprocessRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x0f248596480054786f7ad5e2947ae7e05f45db5c46d1665fc107df232042e28c", + "receipt": { + "to": null, + "from": "0x282607716D9B4fDD0B094d5864fac56313f5e665", + "contractAddress": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "transactionIndex": 65, + "gasUsed": "3489875", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000020000000000000000000000000000000000000001000000000000000000000000000000000000000000040000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000000000000000000000000000", + "blockHash": "0x8c912c68e68e048d0710c1d98712dae3b8d9154d73834014b4ed94c791420565", + "transactionHash": "0x0f248596480054786f7ad5e2947ae7e05f45db5c46d1665fc107df232042e28c", + "logs": [ + { + "transactionIndex": 65, + "blockNumber": 17724136, + "transactionHash": "0x0f248596480054786f7ad5e2947ae7e05f45db5c46d1665fc107df232042e28c", + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000282607716d9b4fdd0b094d5864fac56313f5e665" + ], + "data": "0x", + "logIndex": 161, + "blockHash": "0x8c912c68e68e048d0710c1d98712dae3b8d9154d73834014b4ed94c791420565" + } + ], + "blockNumber": 17724136, + "cumulativeGasUsed": "13483788", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000000", + [] + ], + "numDeployments": 1, + "solcInputHash": "e556d43a3caf4f1fb4f12d632d103b28", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bentoBox\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"priviledgedUserList\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"MinimalOutputBalanceViolation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"Route\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"algebraSwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"pancakeV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"priviledgedUsers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"priviledge\",\"type\":\"bool\"}],\"name\":\"setPriviledge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"transferValueAndprocessRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"Ilya Lyalin\",\"kind\":\"dev\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IAlgebraPoolActions#swap call\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the PancakeV3Pool#swap call\"}},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"route\":\"Route to process\",\"to\":\"Where to transfer output tokens\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IUniswapV3PoolActions#swap call\"}}},\"title\":\"A route processor for the Sushi Aggregator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\"},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Processes the route generated off-chain. Has a lock\"},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value of input tokens to and then processes the route\"},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"processes the route and sends amount of output token to \"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value to and then processes the route\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RouteProcessor5.sol\":\"RouteProcessor5\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\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 Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.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 function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\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\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\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 * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\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\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/InputStream.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\n/** @notice Simple read stream */\\nlibrary InputStream {\\n\\n /** @notice Creates stream from data\\n * @param data data\\n */\\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\\n assembly {\\n stream := mload(0x40)\\n mstore(0x40, add(stream, 64))\\n mstore(stream, data)\\n let length := mload(data)\\n mstore(add(stream, 32), add(data, length))\\n }\\n }\\n\\n /** @notice Checks if stream is not empty\\n * @param stream stream\\n */\\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\\n uint256 pos;\\n uint256 finish;\\n assembly {\\n pos := mload(stream)\\n finish := mload(add(stream, 32))\\n }\\n return pos < finish;\\n }\\n\\n /** @notice Reads uint8 from the stream\\n * @param stream stream\\n */\\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 1)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint16 from the stream\\n * @param stream stream\\n */\\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 2)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint24 from the stream\\n * @param stream stream\\n */\\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 3)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint32 from the stream\\n * @param stream stream\\n */\\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 4)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint256 from the stream\\n * @param stream stream\\n */\\n function readUint(uint256 stream) internal pure returns (uint256 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes32 from the stream\\n * @param stream stream\\n */\\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads address from the stream\\n * @param stream stream\\n */\\n function readAddress(uint256 stream) internal pure returns (address res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 20)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes from the stream\\n * @param stream stream\\n */\\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\\n assembly {\\n let pos := mload(stream)\\n res := add(pos, 32)\\n let length := mload(res)\\n mstore(stream, add(res, length))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x24e24bd0e49cbddacbf3b26bcd4bdffac63d11f3259bc05bc93c0835e8ff5300\",\"license\":\"UNLICENSED\"},\"contracts/RouteProcessor5.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '../interfaces/IUniswapV2Pair.sol';\\nimport '../interfaces/IUniswapV3Pool.sol';\\nimport '../interfaces/ITridentCLPool.sol';\\nimport '../interfaces/IBentoBoxMinimal.sol';\\nimport '../interfaces/IPool.sol';\\nimport '../interfaces/IWETH.sol';\\nimport '../interfaces/ICurve.sol';\\nimport './InputStream.sol';\\nimport './Utils.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\\n\\nuint8 constant LOCKED = 2;\\nuint8 constant NOT_LOCKED = 1;\\nuint8 constant PAUSED = 2;\\nuint8 constant NOT_PAUSED = 1;\\n\\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\nuint160 constant MIN_SQRT_RATIO = 4295128739;\\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n/// @title A route processor for the Sushi Aggregator\\n/// @author Ilya Lyalin\\ncontract RouteProcessor5 is Ownable {\\n using SafeERC20 for IERC20;\\n using Utils for IERC20;\\n using Utils for address;\\n using SafeERC20 for IERC20Permit;\\n using InputStream for uint256;\\n\\n event Route(\\n address indexed from, \\n address to, \\n address indexed tokenIn, \\n address indexed tokenOut, \\n uint256 amountIn, \\n uint256 amountOutMin,\\n uint256 amountOut\\n );\\n\\n error MinimalOutputBalanceViolation(uint256 amountOut);\\n\\n IBentoBoxMinimal public immutable bentoBox;\\n mapping (address => bool) public priviledgedUsers;\\n address private lastCalledPool;\\n\\n uint8 private unlocked = NOT_LOCKED;\\n uint8 private paused = NOT_PAUSED;\\n modifier lock() {\\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\\n unlocked = LOCKED;\\n _;\\n unlocked = NOT_LOCKED;\\n }\\n\\n modifier onlyOwnerOrPriviledgedUser() {\\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \\\"RP: caller is not the owner or a privileged user\\\");\\n _;\\n }\\n\\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\\n bentoBox = IBentoBoxMinimal(_bentoBox);\\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n\\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\\n priviledgedUsers[priviledgedUserList[i]] = true;\\n }\\n }\\n\\n function setPriviledge(address user, bool priviledge) external onlyOwner {\\n priviledgedUsers[user] = priviledge;\\n }\\n\\n function pause() external onlyOwnerOrPriviledgedUser {\\n paused = PAUSED;\\n }\\n\\n function resume() external onlyOwnerOrPriviledgedUser {\\n paused = NOT_PAUSED;\\n }\\n\\n /// @notice For native unwrapping\\n receive() external payable {}\\n\\n /// @notice Processes the route generated off-chain. Has a lock\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @param to Where to transfer output tokens\\n /// @param route Route to process\\n /// @return amountOut Actual amount of the output token\\n function processRoute(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function transferValueAndprocessRoute(\\n address transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n transferValueTo.transferNative(amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value of input tokens to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueInput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n \\n /// @notice processes the route and sends amount of output token to \\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueOutput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\\n }\\n\\n /// @notice Processes the route generated off-chain\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteInternal(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) private returns (uint256 amountOut) {\\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\\n\\n uint256 realAmountIn = amountIn;\\n {\\n uint256 step = 0;\\n uint256 stream = InputStream.createStream(route);\\n while (stream.isNotEmpty()) {\\n uint8 commandCode = stream.readUint8();\\n if (commandCode == 1) {\\n uint256 usedAmount = processMyERC20(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 2) processUserERC20(stream, amountIn);\\n else if (commandCode == 3) {\\n uint256 usedAmount = processNative(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 4) processOnePool(stream);\\n else if (commandCode == 5) processInsideBento(stream);\\n else if (commandCode == 6) applyPermit(tokenIn, stream);\\n else revert('RouteProcessor: Unknown command code');\\n ++step;\\n }\\n }\\n\\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\\n if (tokenIn != Utils.NATIVE_ADDRESS)\\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\\n \\n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\\n\\n amountOut = balanceOutFinal - balanceOutInitial;\\n\\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\\n }\\n\\n /// @notice Applies ERC-2612 permit\\n /// @param tokenIn permitted token\\n /// @param stream Streamed program\\n function applyPermit(address tokenIn, uint256 stream) private {\\n uint256 value = stream.readUint();\\n uint256 deadline = stream.readUint();\\n uint8 v = stream.readUint8();\\n bytes32 r = stream.readBytes32();\\n bytes32 s = stream.readBytes32();\\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\\n }\\n }\\n\\n /// @notice Processes native coin: call swap for all pools that swap from native coin\\n /// @param stream Streamed program\\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\\n amountTotal = address(this).balance;\\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token from this contract balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\\n address token = stream.readAddress();\\n amountTotal = IERC20(token).balanceOf(address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n \\n /// @notice Processes ERC20 token from msg.sender balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n /// @param amountTotal Amount of tokens to take from msg.sender\\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\\n address token = stream.readAddress();\\n distributeAndSwap(stream, msg.sender, token, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token for cases when the token has only one output pool\\n /// @notice In this case liquidity is already at pool balance. This is an optimization\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processOnePool(uint256 stream) private {\\n address token = stream.readAddress();\\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\\n }\\n\\n /// @notice Processes Bento tokens \\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processInsideBento(uint256 stream) private {\\n address token = stream.readAddress();\\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n\\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountTotal Total amount of tokenIn for swaps \\n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\\n uint8 num = stream.readUint8();\\n unchecked {\\n for (uint256 i = 0; i < num; ++i) {\\n uint16 share = stream.readUint16();\\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\\n amountTotal -= amount;\\n swap(stream, from, tokenIn, amount);\\n }\\n }\\n }\\n\\n /// @notice Makes swap\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 poolType = stream.readUint8();\\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\\n else revert('RouteProcessor: Unknown pool type');\\n }\\n\\n /// @notice Wraps/unwraps native token\\n /// @param stream [direction & fake, recipient, wrapToken?]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 directionAndFake = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (directionAndFake & 1 == 1) { // wrap native\\n address wrapToken = stream.readAddress();\\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\\n } else { // unwrap native\\n if (directionAndFake & 2 == 0) {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IWETH(tokenIn).withdraw(amountIn);\\n }\\n to.transferNative(amountIn);\\n }\\n }\\n\\n /// @notice Bridge/unbridge tokens to/from Bento\\n /// @param stream [direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (direction > 0) { // outside to Bento\\n // deposit to arbitrary recipient is possible only from address(bentoBox)\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\\n else {\\n // tokens already are at address(bentoBox)\\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\\n bentoBox.strategyData(tokenIn).balance -\\n bentoBox.totals(tokenIn).elastic;\\n }\\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\\n } else { // Bento to outside\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\\n }\\n }\\n\\n /// @notice UniswapV2 pool swap\\n /// @param stream [pool, direction, recipient, fee]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\\n\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\\n\\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\\n\\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\\n }\\n\\n /// @notice Trident pool swap\\n /// @param stream [pool, swapData]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bytes memory swapData = stream.readBytes();\\n\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, pool, amountIn);\\n }\\n \\n IPool(pool).swap(swapData);\\n }\\n\\n /// @notice UniswapV3 pool swap\\n /// @param stream [pool, direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bool zeroForOne = stream.readUint8() > 0;\\n address recipient = stream.readAddress();\\n\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\\n\\n lastCalledPool = pool;\\n IUniswapV3Pool(pool).swap(\\n recipient,\\n zeroForOne,\\n int256(amountIn),\\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\\n abi.encode(tokenIn)\\n );\\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) public {\\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\\n \\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n (address tokenIn) = abi.decode(data, (address));\\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\\n function algebraSwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\\n function pancakeV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 poolType = stream.readUint8();\\n int128 fromIndex = int8(stream.readUint8());\\n int128 toIndex = int8(stream.readUint8());\\n address to = stream.readAddress();\\n address tokenOut = stream.readAddress();\\n\\n uint256 amountOut;\\n if (tokenIn == Utils.NATIVE_ADDRESS) {\\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\\n } else {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IERC20(tokenIn).approveSafe(pool, amountIn);\\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n else {\\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\\n amountOut = balanceAfter - balanceBefore;\\n }\\n }\\n\\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\\n }\\n}\\n\",\"keccak256\":\"0xcd53a7f473f1847d44c42777a194203cbff02b8c761cb2935402401f57c918a2\",\"license\":\"UNLICENSED\"},\"contracts/Utils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\n\\nlibrary Utils {\\n using SafeERC20 for IERC20;\\n\\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n /**\\n * @dev returns user's balance of token (or native)\\n */\\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\\n if (token == NATIVE_ADDRESS) return address(user).balance;\\n else return IERC20(token).balanceOf(user);\\n }\\n\\n /**\\n * @dev transfers native with correct revert bubble up\\n */\\n function transferNative(address to, uint256 amount) internal {\\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\\n if (!success) {\\n assembly {\\n revert(add(32, returnBytes), mload(returnBytes))\\n }\\n }\\n }\\n\\n /**\\n * @dev transfers ERC20 or native\\n */\\n function transferAny(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\\n else IERC20(token).safeTransfer(to, amount);\\n }\\n\\n /**\\n * @dev transfers from ERC20 or transfers native\\n */\\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n (bool success, bytes memory data) = address(token).call(\\n abi.encodeWithSelector(token.approve.selector, spender, amount)\\n );\\n return success && (data.length == 0 || abi.decode(data, (bool)));\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \\n * current allowance are not zero simultaniously (USDT for example). \\n * In second case it tries to set allowance to 0, and then back to amount.\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n return approveStable(token, spender, amount) \\n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\\n }\\n}\\n\",\"keccak256\":\"0x8c8439edc00b403abd3f34be75a06b1fe71152644ae9f19488af596bbc534ffe\",\"license\":\"UNLICENSED\"},\"interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\nstruct StrategyData {\\n uint64 strategyStartDate;\\n uint64 targetPercentage;\\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n function strategyData(address token) external view returns (StrategyData memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0x0c12eba7a5b9d22d37ab8883fe22d6a312a90682809dbd11c43f8e6ceaff73bf\",\"license\":\"UNLICENSED\"},\"interfaces/ICurve.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\ninterface ICurve {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\\n}\\n\\ninterface ICurveLegacy {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\\n}\\n\\n\",\"keccak256\":\"0x3d4940b3583e06dde20f12e92d2f6ac573b3f64bdaa1e8f480656a3763852518\",\"license\":\"UNLICENSED\"},\"interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/ITridentCLPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface ITridentCLPool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bool unwrapBento,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x572376b80c86a94692b0e27e6e63790b763295e32ba1f956c1d331fc1296de8d\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IUniswapV2Pair.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Pair {\\n event Approval(address indexed owner, address indexed spender, uint value);\\n event Transfer(address indexed from, address indexed to, uint value);\\n\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function allowance(address owner, address spender) external view returns (uint);\\n\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address to, uint value) external returns (bool);\\n function transferFrom(address from, address to, uint value) external returns (bool);\\n\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n function nonces(address owner) external view returns (uint);\\n\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n event Mint(address indexed sender, uint amount0, uint amount1);\\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\\n event Swap(\\n address indexed sender,\\n uint amount0In,\\n uint amount1In,\\n uint amount0Out,\\n uint amount1Out,\\n address indexed to\\n );\\n event Sync(uint112 reserve0, uint112 reserve1);\\n\\n function MINIMUM_LIQUIDITY() external pure returns (uint);\\n function factory() external view returns (address);\\n function token0() external view returns (address);\\n function token1() external view returns (address);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\\n function price0CumulativeLast() external view returns (uint);\\n function price1CumulativeLast() external view returns (uint);\\n function kLast() external view returns (uint);\\n\\n function mint(address to) external returns (uint liquidity);\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function skim(address to) external;\\n function sync() external;\\n\\n function initialize(address, address) external;\\n}\",\"keccak256\":\"0x08f9a63b34855eec941be8d36a04424f1a1725a2c030373fcef3afeb480ca385\",\"license\":\"GPL-3.0\"},\"interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IUniswapV3Pool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x2a4d7c6120e613f0e95d4dc8c650efb9b59e3c25c64e3e5c0a379281500f0a79\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IWETH.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0xae8529ae159f784b90fdcd0629bd03bf7b68accc81edccac53357ad08406a378\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}", + "bytecode": "0x60a06040526002805461ffff60a01b191661010160a01b1790553480156200002657600080fd5b50604051620040a3380380620040a383398101604081905262000049916200016e565b6200005433620000eb565b6001600160a01b038216608052600280546001600160a01b031916600117905560005b8151811015620000e25760018060008484815181106200009b576200009b62000257565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000d9816200026d565b91505062000077565b50505062000297565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200015357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200018257600080fd5b6200018d836200013b565b602084810151919350906001600160401b0380821115620001ad57600080fd5b818601915086601f830112620001c257600080fd5b815181811115620001d757620001d762000158565b8060051b604051601f19603f83011681018181108582111715620001ff57620001ff62000158565b6040529182528482019250838101850191898311156200021e57600080fd5b938501935b82851015620002475762000237856200013b565b8452938501939285019262000223565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200029057634e487b7160e01b600052601160045260246000fd5b5060010190565b608051613da3620003006000396000818161018d01528181611798015281816127380152818161279d01528181612807015281816128cc0152818161297901528181612a5d01528181612b6401528181612c1001528181612cdf0152612df10152613da36000f3fe6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "deployedBytecode": "0x6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "devdoc": { + "author": "Ilya Lyalin", + "kind": "dev", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IAlgebraPoolActions#swap call" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the PancakeV3Pool#swap call" + } + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "route": "Route to process", + "to": "Where to transfer output tokens", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IUniswapV3PoolActions#swap call" + } + } + }, + "title": "A route processor for the Sushi Aggregator", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IAlgebraPool#swap." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via PancakeV3Pool#swap." + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "notice": "Processes the route generated off-chain. Has a lock" + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value of input tokens to and then processes the route" + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "processes the route and sends amount of output token to " + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value to and then processes the route" + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 1060, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "priviledgedUsers", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 1062, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "lastCalledPool", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 1065, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "unlocked", + "offset": 20, + "slot": "2", + "type": "t_uint8" + }, + { + "astId": 1068, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "paused", + "offset": 21, + "slot": "2", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/base/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json b/protocols/route-processor/deployments/base/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json new file mode 100644 index 0000000000..01826e7b93 --- /dev/null +++ b/protocols/route-processor/deployments/base/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json @@ -0,0 +1,80 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" + }, + "contracts/InputStream.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" + }, + "contracts/RouteProcessor5.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" + }, + "contracts/Utils.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "interfaces/IBentoBoxMinimal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" + }, + "interfaces/ICurve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" + }, + "interfaces/IPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" + }, + "interfaces/ITridentCLPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/blast/RouteProcessor5.json b/protocols/route-processor/deployments/blast/RouteProcessor5.json new file mode 100644 index 0000000000..47741d7a26 --- /dev/null +++ b/protocols/route-processor/deployments/blast/RouteProcessor5.json @@ -0,0 +1,704 @@ +{ + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_bentoBox", + "type": "address" + }, + { + "internalType": "address[]", + "name": "priviledgedUserList", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "MinimalOutputBalanceViolation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Route", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "algebraSwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bentoBox", + "outputs": [ + { + "internalType": "contract IBentoBoxMinimal", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "pancakeV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "priviledgedUsers", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueInput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "priviledge", + "type": "bool" + } + ], + "name": "setPriviledge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "transferValueAndprocessRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0xcb8f1ff4200e5352417c80ce599297192214e5780f7485d1ef1949a6227edfc8", + "receipt": { + "to": null, + "from": "0x282607716D9B4fDD0B094d5864fac56313f5e665", + "contractAddress": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "transactionIndex": 2, + "gasUsed": "3489875", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000020000000000000000000000000000000000000001000000000000000000000000000000000000000000040000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000000000000000000000000000", + "blockHash": "0x6d7cab5f93268710f7b3e34c21bc3ce41b800bb68085b70c29dfc92d81a9f1a5", + "transactionHash": "0xcb8f1ff4200e5352417c80ce599297192214e5780f7485d1ef1949a6227edfc8", + "logs": [ + { + "transactionIndex": 2, + "blockNumber": 6714260, + "transactionHash": "0xcb8f1ff4200e5352417c80ce599297192214e5780f7485d1ef1949a6227edfc8", + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000282607716d9b4fdd0b094d5864fac56313f5e665" + ], + "data": "0x", + "logIndex": 2, + "blockHash": "0x6d7cab5f93268710f7b3e34c21bc3ce41b800bb68085b70c29dfc92d81a9f1a5" + } + ], + "blockNumber": 6714260, + "cumulativeGasUsed": "4598155", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000000", + [] + ], + "numDeployments": 1, + "solcInputHash": "e556d43a3caf4f1fb4f12d632d103b28", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bentoBox\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"priviledgedUserList\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"MinimalOutputBalanceViolation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"Route\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"algebraSwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"pancakeV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"priviledgedUsers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"priviledge\",\"type\":\"bool\"}],\"name\":\"setPriviledge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"transferValueAndprocessRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"Ilya Lyalin\",\"kind\":\"dev\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IAlgebraPoolActions#swap call\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the PancakeV3Pool#swap call\"}},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"route\":\"Route to process\",\"to\":\"Where to transfer output tokens\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IUniswapV3PoolActions#swap call\"}}},\"title\":\"A route processor for the Sushi Aggregator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\"},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Processes the route generated off-chain. Has a lock\"},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value of input tokens to and then processes the route\"},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"processes the route and sends amount of output token to \"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value to and then processes the route\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RouteProcessor5.sol\":\"RouteProcessor5\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\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 Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.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 function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\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\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\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 * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\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\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/InputStream.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\n/** @notice Simple read stream */\\nlibrary InputStream {\\n\\n /** @notice Creates stream from data\\n * @param data data\\n */\\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\\n assembly {\\n stream := mload(0x40)\\n mstore(0x40, add(stream, 64))\\n mstore(stream, data)\\n let length := mload(data)\\n mstore(add(stream, 32), add(data, length))\\n }\\n }\\n\\n /** @notice Checks if stream is not empty\\n * @param stream stream\\n */\\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\\n uint256 pos;\\n uint256 finish;\\n assembly {\\n pos := mload(stream)\\n finish := mload(add(stream, 32))\\n }\\n return pos < finish;\\n }\\n\\n /** @notice Reads uint8 from the stream\\n * @param stream stream\\n */\\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 1)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint16 from the stream\\n * @param stream stream\\n */\\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 2)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint24 from the stream\\n * @param stream stream\\n */\\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 3)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint32 from the stream\\n * @param stream stream\\n */\\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 4)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint256 from the stream\\n * @param stream stream\\n */\\n function readUint(uint256 stream) internal pure returns (uint256 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes32 from the stream\\n * @param stream stream\\n */\\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads address from the stream\\n * @param stream stream\\n */\\n function readAddress(uint256 stream) internal pure returns (address res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 20)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes from the stream\\n * @param stream stream\\n */\\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\\n assembly {\\n let pos := mload(stream)\\n res := add(pos, 32)\\n let length := mload(res)\\n mstore(stream, add(res, length))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x24e24bd0e49cbddacbf3b26bcd4bdffac63d11f3259bc05bc93c0835e8ff5300\",\"license\":\"UNLICENSED\"},\"contracts/RouteProcessor5.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '../interfaces/IUniswapV2Pair.sol';\\nimport '../interfaces/IUniswapV3Pool.sol';\\nimport '../interfaces/ITridentCLPool.sol';\\nimport '../interfaces/IBentoBoxMinimal.sol';\\nimport '../interfaces/IPool.sol';\\nimport '../interfaces/IWETH.sol';\\nimport '../interfaces/ICurve.sol';\\nimport './InputStream.sol';\\nimport './Utils.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\\n\\nuint8 constant LOCKED = 2;\\nuint8 constant NOT_LOCKED = 1;\\nuint8 constant PAUSED = 2;\\nuint8 constant NOT_PAUSED = 1;\\n\\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\nuint160 constant MIN_SQRT_RATIO = 4295128739;\\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n/// @title A route processor for the Sushi Aggregator\\n/// @author Ilya Lyalin\\ncontract RouteProcessor5 is Ownable {\\n using SafeERC20 for IERC20;\\n using Utils for IERC20;\\n using Utils for address;\\n using SafeERC20 for IERC20Permit;\\n using InputStream for uint256;\\n\\n event Route(\\n address indexed from, \\n address to, \\n address indexed tokenIn, \\n address indexed tokenOut, \\n uint256 amountIn, \\n uint256 amountOutMin,\\n uint256 amountOut\\n );\\n\\n error MinimalOutputBalanceViolation(uint256 amountOut);\\n\\n IBentoBoxMinimal public immutable bentoBox;\\n mapping (address => bool) public priviledgedUsers;\\n address private lastCalledPool;\\n\\n uint8 private unlocked = NOT_LOCKED;\\n uint8 private paused = NOT_PAUSED;\\n modifier lock() {\\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\\n unlocked = LOCKED;\\n _;\\n unlocked = NOT_LOCKED;\\n }\\n\\n modifier onlyOwnerOrPriviledgedUser() {\\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \\\"RP: caller is not the owner or a privileged user\\\");\\n _;\\n }\\n\\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\\n bentoBox = IBentoBoxMinimal(_bentoBox);\\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n\\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\\n priviledgedUsers[priviledgedUserList[i]] = true;\\n }\\n }\\n\\n function setPriviledge(address user, bool priviledge) external onlyOwner {\\n priviledgedUsers[user] = priviledge;\\n }\\n\\n function pause() external onlyOwnerOrPriviledgedUser {\\n paused = PAUSED;\\n }\\n\\n function resume() external onlyOwnerOrPriviledgedUser {\\n paused = NOT_PAUSED;\\n }\\n\\n /// @notice For native unwrapping\\n receive() external payable {}\\n\\n /// @notice Processes the route generated off-chain. Has a lock\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @param to Where to transfer output tokens\\n /// @param route Route to process\\n /// @return amountOut Actual amount of the output token\\n function processRoute(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function transferValueAndprocessRoute(\\n address transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n transferValueTo.transferNative(amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value of input tokens to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueInput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n \\n /// @notice processes the route and sends amount of output token to \\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueOutput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\\n }\\n\\n /// @notice Processes the route generated off-chain\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteInternal(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) private returns (uint256 amountOut) {\\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\\n\\n uint256 realAmountIn = amountIn;\\n {\\n uint256 step = 0;\\n uint256 stream = InputStream.createStream(route);\\n while (stream.isNotEmpty()) {\\n uint8 commandCode = stream.readUint8();\\n if (commandCode == 1) {\\n uint256 usedAmount = processMyERC20(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 2) processUserERC20(stream, amountIn);\\n else if (commandCode == 3) {\\n uint256 usedAmount = processNative(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 4) processOnePool(stream);\\n else if (commandCode == 5) processInsideBento(stream);\\n else if (commandCode == 6) applyPermit(tokenIn, stream);\\n else revert('RouteProcessor: Unknown command code');\\n ++step;\\n }\\n }\\n\\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\\n if (tokenIn != Utils.NATIVE_ADDRESS)\\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\\n \\n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\\n\\n amountOut = balanceOutFinal - balanceOutInitial;\\n\\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\\n }\\n\\n /// @notice Applies ERC-2612 permit\\n /// @param tokenIn permitted token\\n /// @param stream Streamed program\\n function applyPermit(address tokenIn, uint256 stream) private {\\n uint256 value = stream.readUint();\\n uint256 deadline = stream.readUint();\\n uint8 v = stream.readUint8();\\n bytes32 r = stream.readBytes32();\\n bytes32 s = stream.readBytes32();\\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\\n }\\n }\\n\\n /// @notice Processes native coin: call swap for all pools that swap from native coin\\n /// @param stream Streamed program\\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\\n amountTotal = address(this).balance;\\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token from this contract balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\\n address token = stream.readAddress();\\n amountTotal = IERC20(token).balanceOf(address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n \\n /// @notice Processes ERC20 token from msg.sender balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n /// @param amountTotal Amount of tokens to take from msg.sender\\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\\n address token = stream.readAddress();\\n distributeAndSwap(stream, msg.sender, token, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token for cases when the token has only one output pool\\n /// @notice In this case liquidity is already at pool balance. This is an optimization\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processOnePool(uint256 stream) private {\\n address token = stream.readAddress();\\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\\n }\\n\\n /// @notice Processes Bento tokens \\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processInsideBento(uint256 stream) private {\\n address token = stream.readAddress();\\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n\\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountTotal Total amount of tokenIn for swaps \\n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\\n uint8 num = stream.readUint8();\\n unchecked {\\n for (uint256 i = 0; i < num; ++i) {\\n uint16 share = stream.readUint16();\\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\\n amountTotal -= amount;\\n swap(stream, from, tokenIn, amount);\\n }\\n }\\n }\\n\\n /// @notice Makes swap\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 poolType = stream.readUint8();\\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\\n else revert('RouteProcessor: Unknown pool type');\\n }\\n\\n /// @notice Wraps/unwraps native token\\n /// @param stream [direction & fake, recipient, wrapToken?]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 directionAndFake = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (directionAndFake & 1 == 1) { // wrap native\\n address wrapToken = stream.readAddress();\\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\\n } else { // unwrap native\\n if (directionAndFake & 2 == 0) {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IWETH(tokenIn).withdraw(amountIn);\\n }\\n to.transferNative(amountIn);\\n }\\n }\\n\\n /// @notice Bridge/unbridge tokens to/from Bento\\n /// @param stream [direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (direction > 0) { // outside to Bento\\n // deposit to arbitrary recipient is possible only from address(bentoBox)\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\\n else {\\n // tokens already are at address(bentoBox)\\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\\n bentoBox.strategyData(tokenIn).balance -\\n bentoBox.totals(tokenIn).elastic;\\n }\\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\\n } else { // Bento to outside\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\\n }\\n }\\n\\n /// @notice UniswapV2 pool swap\\n /// @param stream [pool, direction, recipient, fee]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\\n\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\\n\\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\\n\\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\\n }\\n\\n /// @notice Trident pool swap\\n /// @param stream [pool, swapData]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bytes memory swapData = stream.readBytes();\\n\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, pool, amountIn);\\n }\\n \\n IPool(pool).swap(swapData);\\n }\\n\\n /// @notice UniswapV3 pool swap\\n /// @param stream [pool, direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bool zeroForOne = stream.readUint8() > 0;\\n address recipient = stream.readAddress();\\n\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\\n\\n lastCalledPool = pool;\\n IUniswapV3Pool(pool).swap(\\n recipient,\\n zeroForOne,\\n int256(amountIn),\\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\\n abi.encode(tokenIn)\\n );\\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) public {\\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\\n \\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n (address tokenIn) = abi.decode(data, (address));\\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\\n function algebraSwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\\n function pancakeV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 poolType = stream.readUint8();\\n int128 fromIndex = int8(stream.readUint8());\\n int128 toIndex = int8(stream.readUint8());\\n address to = stream.readAddress();\\n address tokenOut = stream.readAddress();\\n\\n uint256 amountOut;\\n if (tokenIn == Utils.NATIVE_ADDRESS) {\\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\\n } else {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IERC20(tokenIn).approveSafe(pool, amountIn);\\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n else {\\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\\n amountOut = balanceAfter - balanceBefore;\\n }\\n }\\n\\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\\n }\\n}\\n\",\"keccak256\":\"0xcd53a7f473f1847d44c42777a194203cbff02b8c761cb2935402401f57c918a2\",\"license\":\"UNLICENSED\"},\"contracts/Utils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\n\\nlibrary Utils {\\n using SafeERC20 for IERC20;\\n\\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n /**\\n * @dev returns user's balance of token (or native)\\n */\\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\\n if (token == NATIVE_ADDRESS) return address(user).balance;\\n else return IERC20(token).balanceOf(user);\\n }\\n\\n /**\\n * @dev transfers native with correct revert bubble up\\n */\\n function transferNative(address to, uint256 amount) internal {\\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\\n if (!success) {\\n assembly {\\n revert(add(32, returnBytes), mload(returnBytes))\\n }\\n }\\n }\\n\\n /**\\n * @dev transfers ERC20 or native\\n */\\n function transferAny(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\\n else IERC20(token).safeTransfer(to, amount);\\n }\\n\\n /**\\n * @dev transfers from ERC20 or transfers native\\n */\\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n (bool success, bytes memory data) = address(token).call(\\n abi.encodeWithSelector(token.approve.selector, spender, amount)\\n );\\n return success && (data.length == 0 || abi.decode(data, (bool)));\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \\n * current allowance are not zero simultaniously (USDT for example). \\n * In second case it tries to set allowance to 0, and then back to amount.\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n return approveStable(token, spender, amount) \\n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\\n }\\n}\\n\",\"keccak256\":\"0x8c8439edc00b403abd3f34be75a06b1fe71152644ae9f19488af596bbc534ffe\",\"license\":\"UNLICENSED\"},\"interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\nstruct StrategyData {\\n uint64 strategyStartDate;\\n uint64 targetPercentage;\\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n function strategyData(address token) external view returns (StrategyData memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0x0c12eba7a5b9d22d37ab8883fe22d6a312a90682809dbd11c43f8e6ceaff73bf\",\"license\":\"UNLICENSED\"},\"interfaces/ICurve.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\ninterface ICurve {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\\n}\\n\\ninterface ICurveLegacy {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\\n}\\n\\n\",\"keccak256\":\"0x3d4940b3583e06dde20f12e92d2f6ac573b3f64bdaa1e8f480656a3763852518\",\"license\":\"UNLICENSED\"},\"interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/ITridentCLPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface ITridentCLPool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bool unwrapBento,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x572376b80c86a94692b0e27e6e63790b763295e32ba1f956c1d331fc1296de8d\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IUniswapV2Pair.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Pair {\\n event Approval(address indexed owner, address indexed spender, uint value);\\n event Transfer(address indexed from, address indexed to, uint value);\\n\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function allowance(address owner, address spender) external view returns (uint);\\n\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address to, uint value) external returns (bool);\\n function transferFrom(address from, address to, uint value) external returns (bool);\\n\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n function nonces(address owner) external view returns (uint);\\n\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n event Mint(address indexed sender, uint amount0, uint amount1);\\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\\n event Swap(\\n address indexed sender,\\n uint amount0In,\\n uint amount1In,\\n uint amount0Out,\\n uint amount1Out,\\n address indexed to\\n );\\n event Sync(uint112 reserve0, uint112 reserve1);\\n\\n function MINIMUM_LIQUIDITY() external pure returns (uint);\\n function factory() external view returns (address);\\n function token0() external view returns (address);\\n function token1() external view returns (address);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\\n function price0CumulativeLast() external view returns (uint);\\n function price1CumulativeLast() external view returns (uint);\\n function kLast() external view returns (uint);\\n\\n function mint(address to) external returns (uint liquidity);\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function skim(address to) external;\\n function sync() external;\\n\\n function initialize(address, address) external;\\n}\",\"keccak256\":\"0x08f9a63b34855eec941be8d36a04424f1a1725a2c030373fcef3afeb480ca385\",\"license\":\"GPL-3.0\"},\"interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IUniswapV3Pool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x2a4d7c6120e613f0e95d4dc8c650efb9b59e3c25c64e3e5c0a379281500f0a79\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IWETH.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0xae8529ae159f784b90fdcd0629bd03bf7b68accc81edccac53357ad08406a378\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}", + "bytecode": "0x60a06040526002805461ffff60a01b191661010160a01b1790553480156200002657600080fd5b50604051620040a3380380620040a383398101604081905262000049916200016e565b6200005433620000eb565b6001600160a01b038216608052600280546001600160a01b031916600117905560005b8151811015620000e25760018060008484815181106200009b576200009b62000257565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000d9816200026d565b91505062000077565b50505062000297565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200015357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200018257600080fd5b6200018d836200013b565b602084810151919350906001600160401b0380821115620001ad57600080fd5b818601915086601f830112620001c257600080fd5b815181811115620001d757620001d762000158565b8060051b604051601f19603f83011681018181108582111715620001ff57620001ff62000158565b6040529182528482019250838101850191898311156200021e57600080fd5b938501935b82851015620002475762000237856200013b565b8452938501939285019262000223565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200029057634e487b7160e01b600052601160045260246000fd5b5060010190565b608051613da3620003006000396000818161018d01528181611798015281816127380152818161279d01528181612807015281816128cc0152818161297901528181612a5d01528181612b6401528181612c1001528181612cdf0152612df10152613da36000f3fe6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "deployedBytecode": "0x6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "devdoc": { + "author": "Ilya Lyalin", + "kind": "dev", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IAlgebraPoolActions#swap call" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the PancakeV3Pool#swap call" + } + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "route": "Route to process", + "to": "Where to transfer output tokens", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IUniswapV3PoolActions#swap call" + } + } + }, + "title": "A route processor for the Sushi Aggregator", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IAlgebraPool#swap." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via PancakeV3Pool#swap." + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "notice": "Processes the route generated off-chain. Has a lock" + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value of input tokens to and then processes the route" + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "processes the route and sends amount of output token to " + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value to and then processes the route" + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 1060, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "priviledgedUsers", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 1062, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "lastCalledPool", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 1065, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "unlocked", + "offset": 20, + "slot": "2", + "type": "t_uint8" + }, + { + "astId": 1068, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "paused", + "offset": 21, + "slot": "2", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/blast/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json b/protocols/route-processor/deployments/blast/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json new file mode 100644 index 0000000000..01826e7b93 --- /dev/null +++ b/protocols/route-processor/deployments/blast/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json @@ -0,0 +1,80 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" + }, + "contracts/InputStream.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" + }, + "contracts/RouteProcessor5.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" + }, + "contracts/Utils.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "interfaces/IBentoBoxMinimal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" + }, + "interfaces/ICurve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" + }, + "interfaces/IPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" + }, + "interfaces/ITridentCLPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/boba-bnb/RouteProcessor5.json b/protocols/route-processor/deployments/boba-bnb/RouteProcessor5.json new file mode 100644 index 0000000000..2a545701ee --- /dev/null +++ b/protocols/route-processor/deployments/boba-bnb/RouteProcessor5.json @@ -0,0 +1,704 @@ +{ + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_bentoBox", + "type": "address" + }, + { + "internalType": "address[]", + "name": "priviledgedUserList", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "MinimalOutputBalanceViolation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Route", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "algebraSwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bentoBox", + "outputs": [ + { + "internalType": "contract IBentoBoxMinimal", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "pancakeV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "priviledgedUsers", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueInput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "priviledge", + "type": "bool" + } + ], + "name": "setPriviledge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "transferValueAndprocessRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0xa503c6efb2acf3e6427fc2f0205f2a25e903aac91c285bf36909a54d88647417", + "receipt": { + "to": null, + "from": "0x282607716D9B4fDD0B094d5864fac56313f5e665", + "contractAddress": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "transactionIndex": 0, + "gasUsed": "3491440", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000020000000000000000000000000000000000000001000000000000000000000000000000000000000000040000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000000000000000000000000000", + "blockHash": "0x49b32bc91858c37ab2800dbac895ad6c0f4fdfae77ae71b7f05768e7d6626f24", + "transactionHash": "0xa503c6efb2acf3e6427fc2f0205f2a25e903aac91c285bf36909a54d88647417", + "logs": [ + { + "transactionIndex": 0, + "blockNumber": 39633422, + "transactionHash": "0xa503c6efb2acf3e6427fc2f0205f2a25e903aac91c285bf36909a54d88647417", + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000282607716d9b4fdd0b094d5864fac56313f5e665" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0x49b32bc91858c37ab2800dbac895ad6c0f4fdfae77ae71b7f05768e7d6626f24" + } + ], + "blockNumber": 39633422, + "cumulativeGasUsed": "3491440", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000000", + [] + ], + "numDeployments": 1, + "solcInputHash": "e556d43a3caf4f1fb4f12d632d103b28", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bentoBox\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"priviledgedUserList\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"MinimalOutputBalanceViolation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"Route\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"algebraSwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"pancakeV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"priviledgedUsers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"priviledge\",\"type\":\"bool\"}],\"name\":\"setPriviledge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"transferValueAndprocessRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"Ilya Lyalin\",\"kind\":\"dev\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IAlgebraPoolActions#swap call\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the PancakeV3Pool#swap call\"}},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"route\":\"Route to process\",\"to\":\"Where to transfer output tokens\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IUniswapV3PoolActions#swap call\"}}},\"title\":\"A route processor for the Sushi Aggregator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\"},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Processes the route generated off-chain. Has a lock\"},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value of input tokens to and then processes the route\"},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"processes the route and sends amount of output token to \"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value to and then processes the route\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RouteProcessor5.sol\":\"RouteProcessor5\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\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 Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.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 function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\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\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\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 * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\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\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/InputStream.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\n/** @notice Simple read stream */\\nlibrary InputStream {\\n\\n /** @notice Creates stream from data\\n * @param data data\\n */\\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\\n assembly {\\n stream := mload(0x40)\\n mstore(0x40, add(stream, 64))\\n mstore(stream, data)\\n let length := mload(data)\\n mstore(add(stream, 32), add(data, length))\\n }\\n }\\n\\n /** @notice Checks if stream is not empty\\n * @param stream stream\\n */\\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\\n uint256 pos;\\n uint256 finish;\\n assembly {\\n pos := mload(stream)\\n finish := mload(add(stream, 32))\\n }\\n return pos < finish;\\n }\\n\\n /** @notice Reads uint8 from the stream\\n * @param stream stream\\n */\\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 1)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint16 from the stream\\n * @param stream stream\\n */\\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 2)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint24 from the stream\\n * @param stream stream\\n */\\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 3)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint32 from the stream\\n * @param stream stream\\n */\\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 4)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint256 from the stream\\n * @param stream stream\\n */\\n function readUint(uint256 stream) internal pure returns (uint256 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes32 from the stream\\n * @param stream stream\\n */\\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads address from the stream\\n * @param stream stream\\n */\\n function readAddress(uint256 stream) internal pure returns (address res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 20)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes from the stream\\n * @param stream stream\\n */\\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\\n assembly {\\n let pos := mload(stream)\\n res := add(pos, 32)\\n let length := mload(res)\\n mstore(stream, add(res, length))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x24e24bd0e49cbddacbf3b26bcd4bdffac63d11f3259bc05bc93c0835e8ff5300\",\"license\":\"UNLICENSED\"},\"contracts/RouteProcessor5.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '../interfaces/IUniswapV2Pair.sol';\\nimport '../interfaces/IUniswapV3Pool.sol';\\nimport '../interfaces/ITridentCLPool.sol';\\nimport '../interfaces/IBentoBoxMinimal.sol';\\nimport '../interfaces/IPool.sol';\\nimport '../interfaces/IWETH.sol';\\nimport '../interfaces/ICurve.sol';\\nimport './InputStream.sol';\\nimport './Utils.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\\n\\nuint8 constant LOCKED = 2;\\nuint8 constant NOT_LOCKED = 1;\\nuint8 constant PAUSED = 2;\\nuint8 constant NOT_PAUSED = 1;\\n\\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\nuint160 constant MIN_SQRT_RATIO = 4295128739;\\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n/// @title A route processor for the Sushi Aggregator\\n/// @author Ilya Lyalin\\ncontract RouteProcessor5 is Ownable {\\n using SafeERC20 for IERC20;\\n using Utils for IERC20;\\n using Utils for address;\\n using SafeERC20 for IERC20Permit;\\n using InputStream for uint256;\\n\\n event Route(\\n address indexed from, \\n address to, \\n address indexed tokenIn, \\n address indexed tokenOut, \\n uint256 amountIn, \\n uint256 amountOutMin,\\n uint256 amountOut\\n );\\n\\n error MinimalOutputBalanceViolation(uint256 amountOut);\\n\\n IBentoBoxMinimal public immutable bentoBox;\\n mapping (address => bool) public priviledgedUsers;\\n address private lastCalledPool;\\n\\n uint8 private unlocked = NOT_LOCKED;\\n uint8 private paused = NOT_PAUSED;\\n modifier lock() {\\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\\n unlocked = LOCKED;\\n _;\\n unlocked = NOT_LOCKED;\\n }\\n\\n modifier onlyOwnerOrPriviledgedUser() {\\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \\\"RP: caller is not the owner or a privileged user\\\");\\n _;\\n }\\n\\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\\n bentoBox = IBentoBoxMinimal(_bentoBox);\\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n\\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\\n priviledgedUsers[priviledgedUserList[i]] = true;\\n }\\n }\\n\\n function setPriviledge(address user, bool priviledge) external onlyOwner {\\n priviledgedUsers[user] = priviledge;\\n }\\n\\n function pause() external onlyOwnerOrPriviledgedUser {\\n paused = PAUSED;\\n }\\n\\n function resume() external onlyOwnerOrPriviledgedUser {\\n paused = NOT_PAUSED;\\n }\\n\\n /// @notice For native unwrapping\\n receive() external payable {}\\n\\n /// @notice Processes the route generated off-chain. Has a lock\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @param to Where to transfer output tokens\\n /// @param route Route to process\\n /// @return amountOut Actual amount of the output token\\n function processRoute(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function transferValueAndprocessRoute(\\n address transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n transferValueTo.transferNative(amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value of input tokens to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueInput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n \\n /// @notice processes the route and sends amount of output token to \\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueOutput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\\n }\\n\\n /// @notice Processes the route generated off-chain\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteInternal(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) private returns (uint256 amountOut) {\\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\\n\\n uint256 realAmountIn = amountIn;\\n {\\n uint256 step = 0;\\n uint256 stream = InputStream.createStream(route);\\n while (stream.isNotEmpty()) {\\n uint8 commandCode = stream.readUint8();\\n if (commandCode == 1) {\\n uint256 usedAmount = processMyERC20(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 2) processUserERC20(stream, amountIn);\\n else if (commandCode == 3) {\\n uint256 usedAmount = processNative(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 4) processOnePool(stream);\\n else if (commandCode == 5) processInsideBento(stream);\\n else if (commandCode == 6) applyPermit(tokenIn, stream);\\n else revert('RouteProcessor: Unknown command code');\\n ++step;\\n }\\n }\\n\\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\\n if (tokenIn != Utils.NATIVE_ADDRESS)\\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\\n \\n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\\n\\n amountOut = balanceOutFinal - balanceOutInitial;\\n\\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\\n }\\n\\n /// @notice Applies ERC-2612 permit\\n /// @param tokenIn permitted token\\n /// @param stream Streamed program\\n function applyPermit(address tokenIn, uint256 stream) private {\\n uint256 value = stream.readUint();\\n uint256 deadline = stream.readUint();\\n uint8 v = stream.readUint8();\\n bytes32 r = stream.readBytes32();\\n bytes32 s = stream.readBytes32();\\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\\n }\\n }\\n\\n /// @notice Processes native coin: call swap for all pools that swap from native coin\\n /// @param stream Streamed program\\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\\n amountTotal = address(this).balance;\\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token from this contract balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\\n address token = stream.readAddress();\\n amountTotal = IERC20(token).balanceOf(address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n \\n /// @notice Processes ERC20 token from msg.sender balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n /// @param amountTotal Amount of tokens to take from msg.sender\\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\\n address token = stream.readAddress();\\n distributeAndSwap(stream, msg.sender, token, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token for cases when the token has only one output pool\\n /// @notice In this case liquidity is already at pool balance. This is an optimization\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processOnePool(uint256 stream) private {\\n address token = stream.readAddress();\\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\\n }\\n\\n /// @notice Processes Bento tokens \\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processInsideBento(uint256 stream) private {\\n address token = stream.readAddress();\\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n\\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountTotal Total amount of tokenIn for swaps \\n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\\n uint8 num = stream.readUint8();\\n unchecked {\\n for (uint256 i = 0; i < num; ++i) {\\n uint16 share = stream.readUint16();\\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\\n amountTotal -= amount;\\n swap(stream, from, tokenIn, amount);\\n }\\n }\\n }\\n\\n /// @notice Makes swap\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 poolType = stream.readUint8();\\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\\n else revert('RouteProcessor: Unknown pool type');\\n }\\n\\n /// @notice Wraps/unwraps native token\\n /// @param stream [direction & fake, recipient, wrapToken?]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 directionAndFake = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (directionAndFake & 1 == 1) { // wrap native\\n address wrapToken = stream.readAddress();\\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\\n } else { // unwrap native\\n if (directionAndFake & 2 == 0) {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IWETH(tokenIn).withdraw(amountIn);\\n }\\n to.transferNative(amountIn);\\n }\\n }\\n\\n /// @notice Bridge/unbridge tokens to/from Bento\\n /// @param stream [direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (direction > 0) { // outside to Bento\\n // deposit to arbitrary recipient is possible only from address(bentoBox)\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\\n else {\\n // tokens already are at address(bentoBox)\\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\\n bentoBox.strategyData(tokenIn).balance -\\n bentoBox.totals(tokenIn).elastic;\\n }\\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\\n } else { // Bento to outside\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\\n }\\n }\\n\\n /// @notice UniswapV2 pool swap\\n /// @param stream [pool, direction, recipient, fee]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\\n\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\\n\\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\\n\\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\\n }\\n\\n /// @notice Trident pool swap\\n /// @param stream [pool, swapData]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bytes memory swapData = stream.readBytes();\\n\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, pool, amountIn);\\n }\\n \\n IPool(pool).swap(swapData);\\n }\\n\\n /// @notice UniswapV3 pool swap\\n /// @param stream [pool, direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bool zeroForOne = stream.readUint8() > 0;\\n address recipient = stream.readAddress();\\n\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\\n\\n lastCalledPool = pool;\\n IUniswapV3Pool(pool).swap(\\n recipient,\\n zeroForOne,\\n int256(amountIn),\\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\\n abi.encode(tokenIn)\\n );\\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) public {\\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\\n \\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n (address tokenIn) = abi.decode(data, (address));\\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\\n function algebraSwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\\n function pancakeV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 poolType = stream.readUint8();\\n int128 fromIndex = int8(stream.readUint8());\\n int128 toIndex = int8(stream.readUint8());\\n address to = stream.readAddress();\\n address tokenOut = stream.readAddress();\\n\\n uint256 amountOut;\\n if (tokenIn == Utils.NATIVE_ADDRESS) {\\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\\n } else {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IERC20(tokenIn).approveSafe(pool, amountIn);\\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n else {\\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\\n amountOut = balanceAfter - balanceBefore;\\n }\\n }\\n\\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\\n }\\n}\\n\",\"keccak256\":\"0xcd53a7f473f1847d44c42777a194203cbff02b8c761cb2935402401f57c918a2\",\"license\":\"UNLICENSED\"},\"contracts/Utils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\n\\nlibrary Utils {\\n using SafeERC20 for IERC20;\\n\\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n /**\\n * @dev returns user's balance of token (or native)\\n */\\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\\n if (token == NATIVE_ADDRESS) return address(user).balance;\\n else return IERC20(token).balanceOf(user);\\n }\\n\\n /**\\n * @dev transfers native with correct revert bubble up\\n */\\n function transferNative(address to, uint256 amount) internal {\\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\\n if (!success) {\\n assembly {\\n revert(add(32, returnBytes), mload(returnBytes))\\n }\\n }\\n }\\n\\n /**\\n * @dev transfers ERC20 or native\\n */\\n function transferAny(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\\n else IERC20(token).safeTransfer(to, amount);\\n }\\n\\n /**\\n * @dev transfers from ERC20 or transfers native\\n */\\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n (bool success, bytes memory data) = address(token).call(\\n abi.encodeWithSelector(token.approve.selector, spender, amount)\\n );\\n return success && (data.length == 0 || abi.decode(data, (bool)));\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \\n * current allowance are not zero simultaniously (USDT for example). \\n * In second case it tries to set allowance to 0, and then back to amount.\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n return approveStable(token, spender, amount) \\n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\\n }\\n}\\n\",\"keccak256\":\"0x8c8439edc00b403abd3f34be75a06b1fe71152644ae9f19488af596bbc534ffe\",\"license\":\"UNLICENSED\"},\"interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\nstruct StrategyData {\\n uint64 strategyStartDate;\\n uint64 targetPercentage;\\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n function strategyData(address token) external view returns (StrategyData memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0x0c12eba7a5b9d22d37ab8883fe22d6a312a90682809dbd11c43f8e6ceaff73bf\",\"license\":\"UNLICENSED\"},\"interfaces/ICurve.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\ninterface ICurve {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\\n}\\n\\ninterface ICurveLegacy {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\\n}\\n\\n\",\"keccak256\":\"0x3d4940b3583e06dde20f12e92d2f6ac573b3f64bdaa1e8f480656a3763852518\",\"license\":\"UNLICENSED\"},\"interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/ITridentCLPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface ITridentCLPool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bool unwrapBento,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x572376b80c86a94692b0e27e6e63790b763295e32ba1f956c1d331fc1296de8d\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IUniswapV2Pair.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Pair {\\n event Approval(address indexed owner, address indexed spender, uint value);\\n event Transfer(address indexed from, address indexed to, uint value);\\n\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function allowance(address owner, address spender) external view returns (uint);\\n\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address to, uint value) external returns (bool);\\n function transferFrom(address from, address to, uint value) external returns (bool);\\n\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n function nonces(address owner) external view returns (uint);\\n\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n event Mint(address indexed sender, uint amount0, uint amount1);\\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\\n event Swap(\\n address indexed sender,\\n uint amount0In,\\n uint amount1In,\\n uint amount0Out,\\n uint amount1Out,\\n address indexed to\\n );\\n event Sync(uint112 reserve0, uint112 reserve1);\\n\\n function MINIMUM_LIQUIDITY() external pure returns (uint);\\n function factory() external view returns (address);\\n function token0() external view returns (address);\\n function token1() external view returns (address);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\\n function price0CumulativeLast() external view returns (uint);\\n function price1CumulativeLast() external view returns (uint);\\n function kLast() external view returns (uint);\\n\\n function mint(address to) external returns (uint liquidity);\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function skim(address to) external;\\n function sync() external;\\n\\n function initialize(address, address) external;\\n}\",\"keccak256\":\"0x08f9a63b34855eec941be8d36a04424f1a1725a2c030373fcef3afeb480ca385\",\"license\":\"GPL-3.0\"},\"interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IUniswapV3Pool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x2a4d7c6120e613f0e95d4dc8c650efb9b59e3c25c64e3e5c0a379281500f0a79\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IWETH.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0xae8529ae159f784b90fdcd0629bd03bf7b68accc81edccac53357ad08406a378\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}", + "bytecode": "0x60a06040526002805461ffff60a01b191661010160a01b1790553480156200002657600080fd5b50604051620040a3380380620040a383398101604081905262000049916200016e565b6200005433620000eb565b6001600160a01b038216608052600280546001600160a01b031916600117905560005b8151811015620000e25760018060008484815181106200009b576200009b62000257565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000d9816200026d565b91505062000077565b50505062000297565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200015357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200018257600080fd5b6200018d836200013b565b602084810151919350906001600160401b0380821115620001ad57600080fd5b818601915086601f830112620001c257600080fd5b815181811115620001d757620001d762000158565b8060051b604051601f19603f83011681018181108582111715620001ff57620001ff62000158565b6040529182528482019250838101850191898311156200021e57600080fd5b938501935b82851015620002475762000237856200013b565b8452938501939285019262000223565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200029057634e487b7160e01b600052601160045260246000fd5b5060010190565b608051613da3620003006000396000818161018d01528181611798015281816127380152818161279d01528181612807015281816128cc0152818161297901528181612a5d01528181612b6401528181612c1001528181612cdf0152612df10152613da36000f3fe6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "deployedBytecode": "0x6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "devdoc": { + "author": "Ilya Lyalin", + "kind": "dev", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IAlgebraPoolActions#swap call" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the PancakeV3Pool#swap call" + } + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "route": "Route to process", + "to": "Where to transfer output tokens", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IUniswapV3PoolActions#swap call" + } + } + }, + "title": "A route processor for the Sushi Aggregator", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IAlgebraPool#swap." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via PancakeV3Pool#swap." + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "notice": "Processes the route generated off-chain. Has a lock" + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value of input tokens to and then processes the route" + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "processes the route and sends amount of output token to " + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value to and then processes the route" + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 1060, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "priviledgedUsers", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 1062, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "lastCalledPool", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 1065, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "unlocked", + "offset": 20, + "slot": "2", + "type": "t_uint8" + }, + { + "astId": 1068, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "paused", + "offset": 21, + "slot": "2", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/boba-bnb/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json b/protocols/route-processor/deployments/boba-bnb/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json new file mode 100644 index 0000000000..01826e7b93 --- /dev/null +++ b/protocols/route-processor/deployments/boba-bnb/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json @@ -0,0 +1,80 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" + }, + "contracts/InputStream.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" + }, + "contracts/RouteProcessor5.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" + }, + "contracts/Utils.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "interfaces/IBentoBoxMinimal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" + }, + "interfaces/ICurve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" + }, + "interfaces/IPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" + }, + "interfaces/ITridentCLPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/boba/RouteProcessor5.json b/protocols/route-processor/deployments/boba/RouteProcessor5.json new file mode 100644 index 0000000000..bf45fed157 --- /dev/null +++ b/protocols/route-processor/deployments/boba/RouteProcessor5.json @@ -0,0 +1,704 @@ +{ + "address": "0x1f2FCf1d036b375b384012e61D3AA33F8C256bbE", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_bentoBox", + "type": "address" + }, + { + "internalType": "address[]", + "name": "priviledgedUserList", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "MinimalOutputBalanceViolation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Route", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "algebraSwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bentoBox", + "outputs": [ + { + "internalType": "contract IBentoBoxMinimal", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "pancakeV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "priviledgedUsers", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueInput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "priviledge", + "type": "bool" + } + ], + "name": "setPriviledge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "transferValueAndprocessRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x99180d89f8a75b05f527e6ebcb5ae9bd9e40621ee7a3d2fca2815ae92f731bcb", + "receipt": { + "to": null, + "from": "0x69aea8e393e14945EC22f33B422e7269967e6327", + "contractAddress": "0x1f2FCf1d036b375b384012e61D3AA33F8C256bbE", + "transactionIndex": 1, + "gasUsed": "3489875", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000200000000000000000000000000020000000000000000000800000000000000000040000000000000400000000000000000000000000000000000000000002100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000080000000020000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x60007d44af8c6cf27f889cd606d783582cb60607049d2bba1eea4cc20e86b7fe", + "transactionHash": "0x99180d89f8a75b05f527e6ebcb5ae9bd9e40621ee7a3d2fca2815ae92f731bcb", + "logs": [ + { + "transactionIndex": 1, + "blockNumber": 5625741, + "transactionHash": "0x99180d89f8a75b05f527e6ebcb5ae9bd9e40621ee7a3d2fca2815ae92f731bcb", + "address": "0x1f2FCf1d036b375b384012e61D3AA33F8C256bbE", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000069aea8e393e14945ec22f33b422e7269967e6327" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0x60007d44af8c6cf27f889cd606d783582cb60607049d2bba1eea4cc20e86b7fe" + } + ], + "blockNumber": 5625741, + "cumulativeGasUsed": "3533690", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000000", + [] + ], + "numDeployments": 1, + "solcInputHash": "e556d43a3caf4f1fb4f12d632d103b28", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bentoBox\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"priviledgedUserList\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"MinimalOutputBalanceViolation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"Route\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"algebraSwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"pancakeV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"priviledgedUsers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"priviledge\",\"type\":\"bool\"}],\"name\":\"setPriviledge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"transferValueAndprocessRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"Ilya Lyalin\",\"kind\":\"dev\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IAlgebraPoolActions#swap call\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the PancakeV3Pool#swap call\"}},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"route\":\"Route to process\",\"to\":\"Where to transfer output tokens\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IUniswapV3PoolActions#swap call\"}}},\"title\":\"A route processor for the Sushi Aggregator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\"},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Processes the route generated off-chain. Has a lock\"},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value of input tokens to and then processes the route\"},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"processes the route and sends amount of output token to \"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value to and then processes the route\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RouteProcessor5.sol\":\"RouteProcessor5\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\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 Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.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 function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\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\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\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 * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\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\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/InputStream.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\n/** @notice Simple read stream */\\nlibrary InputStream {\\n\\n /** @notice Creates stream from data\\n * @param data data\\n */\\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\\n assembly {\\n stream := mload(0x40)\\n mstore(0x40, add(stream, 64))\\n mstore(stream, data)\\n let length := mload(data)\\n mstore(add(stream, 32), add(data, length))\\n }\\n }\\n\\n /** @notice Checks if stream is not empty\\n * @param stream stream\\n */\\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\\n uint256 pos;\\n uint256 finish;\\n assembly {\\n pos := mload(stream)\\n finish := mload(add(stream, 32))\\n }\\n return pos < finish;\\n }\\n\\n /** @notice Reads uint8 from the stream\\n * @param stream stream\\n */\\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 1)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint16 from the stream\\n * @param stream stream\\n */\\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 2)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint24 from the stream\\n * @param stream stream\\n */\\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 3)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint32 from the stream\\n * @param stream stream\\n */\\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 4)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint256 from the stream\\n * @param stream stream\\n */\\n function readUint(uint256 stream) internal pure returns (uint256 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes32 from the stream\\n * @param stream stream\\n */\\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads address from the stream\\n * @param stream stream\\n */\\n function readAddress(uint256 stream) internal pure returns (address res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 20)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes from the stream\\n * @param stream stream\\n */\\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\\n assembly {\\n let pos := mload(stream)\\n res := add(pos, 32)\\n let length := mload(res)\\n mstore(stream, add(res, length))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x24e24bd0e49cbddacbf3b26bcd4bdffac63d11f3259bc05bc93c0835e8ff5300\",\"license\":\"UNLICENSED\"},\"contracts/RouteProcessor5.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '../interfaces/IUniswapV2Pair.sol';\\nimport '../interfaces/IUniswapV3Pool.sol';\\nimport '../interfaces/ITridentCLPool.sol';\\nimport '../interfaces/IBentoBoxMinimal.sol';\\nimport '../interfaces/IPool.sol';\\nimport '../interfaces/IWETH.sol';\\nimport '../interfaces/ICurve.sol';\\nimport './InputStream.sol';\\nimport './Utils.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\\n\\nuint8 constant LOCKED = 2;\\nuint8 constant NOT_LOCKED = 1;\\nuint8 constant PAUSED = 2;\\nuint8 constant NOT_PAUSED = 1;\\n\\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\nuint160 constant MIN_SQRT_RATIO = 4295128739;\\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n/// @title A route processor for the Sushi Aggregator\\n/// @author Ilya Lyalin\\ncontract RouteProcessor5 is Ownable {\\n using SafeERC20 for IERC20;\\n using Utils for IERC20;\\n using Utils for address;\\n using SafeERC20 for IERC20Permit;\\n using InputStream for uint256;\\n\\n event Route(\\n address indexed from, \\n address to, \\n address indexed tokenIn, \\n address indexed tokenOut, \\n uint256 amountIn, \\n uint256 amountOutMin,\\n uint256 amountOut\\n );\\n\\n error MinimalOutputBalanceViolation(uint256 amountOut);\\n\\n IBentoBoxMinimal public immutable bentoBox;\\n mapping (address => bool) public priviledgedUsers;\\n address private lastCalledPool;\\n\\n uint8 private unlocked = NOT_LOCKED;\\n uint8 private paused = NOT_PAUSED;\\n modifier lock() {\\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\\n unlocked = LOCKED;\\n _;\\n unlocked = NOT_LOCKED;\\n }\\n\\n modifier onlyOwnerOrPriviledgedUser() {\\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \\\"RP: caller is not the owner or a privileged user\\\");\\n _;\\n }\\n\\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\\n bentoBox = IBentoBoxMinimal(_bentoBox);\\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n\\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\\n priviledgedUsers[priviledgedUserList[i]] = true;\\n }\\n }\\n\\n function setPriviledge(address user, bool priviledge) external onlyOwner {\\n priviledgedUsers[user] = priviledge;\\n }\\n\\n function pause() external onlyOwnerOrPriviledgedUser {\\n paused = PAUSED;\\n }\\n\\n function resume() external onlyOwnerOrPriviledgedUser {\\n paused = NOT_PAUSED;\\n }\\n\\n /// @notice For native unwrapping\\n receive() external payable {}\\n\\n /// @notice Processes the route generated off-chain. Has a lock\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @param to Where to transfer output tokens\\n /// @param route Route to process\\n /// @return amountOut Actual amount of the output token\\n function processRoute(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function transferValueAndprocessRoute(\\n address transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n transferValueTo.transferNative(amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value of input tokens to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueInput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n \\n /// @notice processes the route and sends amount of output token to \\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueOutput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\\n }\\n\\n /// @notice Processes the route generated off-chain\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteInternal(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) private returns (uint256 amountOut) {\\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\\n\\n uint256 realAmountIn = amountIn;\\n {\\n uint256 step = 0;\\n uint256 stream = InputStream.createStream(route);\\n while (stream.isNotEmpty()) {\\n uint8 commandCode = stream.readUint8();\\n if (commandCode == 1) {\\n uint256 usedAmount = processMyERC20(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 2) processUserERC20(stream, amountIn);\\n else if (commandCode == 3) {\\n uint256 usedAmount = processNative(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 4) processOnePool(stream);\\n else if (commandCode == 5) processInsideBento(stream);\\n else if (commandCode == 6) applyPermit(tokenIn, stream);\\n else revert('RouteProcessor: Unknown command code');\\n ++step;\\n }\\n }\\n\\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\\n if (tokenIn != Utils.NATIVE_ADDRESS)\\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\\n \\n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\\n\\n amountOut = balanceOutFinal - balanceOutInitial;\\n\\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\\n }\\n\\n /// @notice Applies ERC-2612 permit\\n /// @param tokenIn permitted token\\n /// @param stream Streamed program\\n function applyPermit(address tokenIn, uint256 stream) private {\\n uint256 value = stream.readUint();\\n uint256 deadline = stream.readUint();\\n uint8 v = stream.readUint8();\\n bytes32 r = stream.readBytes32();\\n bytes32 s = stream.readBytes32();\\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\\n }\\n }\\n\\n /// @notice Processes native coin: call swap for all pools that swap from native coin\\n /// @param stream Streamed program\\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\\n amountTotal = address(this).balance;\\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token from this contract balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\\n address token = stream.readAddress();\\n amountTotal = IERC20(token).balanceOf(address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n \\n /// @notice Processes ERC20 token from msg.sender balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n /// @param amountTotal Amount of tokens to take from msg.sender\\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\\n address token = stream.readAddress();\\n distributeAndSwap(stream, msg.sender, token, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token for cases when the token has only one output pool\\n /// @notice In this case liquidity is already at pool balance. This is an optimization\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processOnePool(uint256 stream) private {\\n address token = stream.readAddress();\\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\\n }\\n\\n /// @notice Processes Bento tokens \\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processInsideBento(uint256 stream) private {\\n address token = stream.readAddress();\\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n\\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountTotal Total amount of tokenIn for swaps \\n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\\n uint8 num = stream.readUint8();\\n unchecked {\\n for (uint256 i = 0; i < num; ++i) {\\n uint16 share = stream.readUint16();\\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\\n amountTotal -= amount;\\n swap(stream, from, tokenIn, amount);\\n }\\n }\\n }\\n\\n /// @notice Makes swap\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 poolType = stream.readUint8();\\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\\n else revert('RouteProcessor: Unknown pool type');\\n }\\n\\n /// @notice Wraps/unwraps native token\\n /// @param stream [direction & fake, recipient, wrapToken?]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 directionAndFake = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (directionAndFake & 1 == 1) { // wrap native\\n address wrapToken = stream.readAddress();\\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\\n } else { // unwrap native\\n if (directionAndFake & 2 == 0) {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IWETH(tokenIn).withdraw(amountIn);\\n }\\n to.transferNative(amountIn);\\n }\\n }\\n\\n /// @notice Bridge/unbridge tokens to/from Bento\\n /// @param stream [direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (direction > 0) { // outside to Bento\\n // deposit to arbitrary recipient is possible only from address(bentoBox)\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\\n else {\\n // tokens already are at address(bentoBox)\\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\\n bentoBox.strategyData(tokenIn).balance -\\n bentoBox.totals(tokenIn).elastic;\\n }\\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\\n } else { // Bento to outside\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\\n }\\n }\\n\\n /// @notice UniswapV2 pool swap\\n /// @param stream [pool, direction, recipient, fee]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\\n\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\\n\\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\\n\\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\\n }\\n\\n /// @notice Trident pool swap\\n /// @param stream [pool, swapData]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bytes memory swapData = stream.readBytes();\\n\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, pool, amountIn);\\n }\\n \\n IPool(pool).swap(swapData);\\n }\\n\\n /// @notice UniswapV3 pool swap\\n /// @param stream [pool, direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bool zeroForOne = stream.readUint8() > 0;\\n address recipient = stream.readAddress();\\n\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\\n\\n lastCalledPool = pool;\\n IUniswapV3Pool(pool).swap(\\n recipient,\\n zeroForOne,\\n int256(amountIn),\\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\\n abi.encode(tokenIn)\\n );\\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) public {\\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\\n \\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n (address tokenIn) = abi.decode(data, (address));\\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\\n function algebraSwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\\n function pancakeV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 poolType = stream.readUint8();\\n int128 fromIndex = int8(stream.readUint8());\\n int128 toIndex = int8(stream.readUint8());\\n address to = stream.readAddress();\\n address tokenOut = stream.readAddress();\\n\\n uint256 amountOut;\\n if (tokenIn == Utils.NATIVE_ADDRESS) {\\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\\n } else {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IERC20(tokenIn).approveSafe(pool, amountIn);\\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n else {\\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\\n amountOut = balanceAfter - balanceBefore;\\n }\\n }\\n\\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\\n }\\n}\\n\",\"keccak256\":\"0xcd53a7f473f1847d44c42777a194203cbff02b8c761cb2935402401f57c918a2\",\"license\":\"UNLICENSED\"},\"contracts/Utils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\n\\nlibrary Utils {\\n using SafeERC20 for IERC20;\\n\\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n /**\\n * @dev returns user's balance of token (or native)\\n */\\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\\n if (token == NATIVE_ADDRESS) return address(user).balance;\\n else return IERC20(token).balanceOf(user);\\n }\\n\\n /**\\n * @dev transfers native with correct revert bubble up\\n */\\n function transferNative(address to, uint256 amount) internal {\\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\\n if (!success) {\\n assembly {\\n revert(add(32, returnBytes), mload(returnBytes))\\n }\\n }\\n }\\n\\n /**\\n * @dev transfers ERC20 or native\\n */\\n function transferAny(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\\n else IERC20(token).safeTransfer(to, amount);\\n }\\n\\n /**\\n * @dev transfers from ERC20 or transfers native\\n */\\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n (bool success, bytes memory data) = address(token).call(\\n abi.encodeWithSelector(token.approve.selector, spender, amount)\\n );\\n return success && (data.length == 0 || abi.decode(data, (bool)));\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \\n * current allowance are not zero simultaniously (USDT for example). \\n * In second case it tries to set allowance to 0, and then back to amount.\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n return approveStable(token, spender, amount) \\n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\\n }\\n}\\n\",\"keccak256\":\"0x8c8439edc00b403abd3f34be75a06b1fe71152644ae9f19488af596bbc534ffe\",\"license\":\"UNLICENSED\"},\"interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\nstruct StrategyData {\\n uint64 strategyStartDate;\\n uint64 targetPercentage;\\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n function strategyData(address token) external view returns (StrategyData memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0x0c12eba7a5b9d22d37ab8883fe22d6a312a90682809dbd11c43f8e6ceaff73bf\",\"license\":\"UNLICENSED\"},\"interfaces/ICurve.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\ninterface ICurve {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\\n}\\n\\ninterface ICurveLegacy {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\\n}\\n\\n\",\"keccak256\":\"0x3d4940b3583e06dde20f12e92d2f6ac573b3f64bdaa1e8f480656a3763852518\",\"license\":\"UNLICENSED\"},\"interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/ITridentCLPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface ITridentCLPool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bool unwrapBento,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x572376b80c86a94692b0e27e6e63790b763295e32ba1f956c1d331fc1296de8d\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IUniswapV2Pair.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Pair {\\n event Approval(address indexed owner, address indexed spender, uint value);\\n event Transfer(address indexed from, address indexed to, uint value);\\n\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function allowance(address owner, address spender) external view returns (uint);\\n\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address to, uint value) external returns (bool);\\n function transferFrom(address from, address to, uint value) external returns (bool);\\n\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n function nonces(address owner) external view returns (uint);\\n\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n event Mint(address indexed sender, uint amount0, uint amount1);\\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\\n event Swap(\\n address indexed sender,\\n uint amount0In,\\n uint amount1In,\\n uint amount0Out,\\n uint amount1Out,\\n address indexed to\\n );\\n event Sync(uint112 reserve0, uint112 reserve1);\\n\\n function MINIMUM_LIQUIDITY() external pure returns (uint);\\n function factory() external view returns (address);\\n function token0() external view returns (address);\\n function token1() external view returns (address);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\\n function price0CumulativeLast() external view returns (uint);\\n function price1CumulativeLast() external view returns (uint);\\n function kLast() external view returns (uint);\\n\\n function mint(address to) external returns (uint liquidity);\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function skim(address to) external;\\n function sync() external;\\n\\n function initialize(address, address) external;\\n}\",\"keccak256\":\"0x08f9a63b34855eec941be8d36a04424f1a1725a2c030373fcef3afeb480ca385\",\"license\":\"GPL-3.0\"},\"interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IUniswapV3Pool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x2a4d7c6120e613f0e95d4dc8c650efb9b59e3c25c64e3e5c0a379281500f0a79\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IWETH.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0xae8529ae159f784b90fdcd0629bd03bf7b68accc81edccac53357ad08406a378\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}", + "bytecode": "0x60a06040526002805461ffff60a01b191661010160a01b1790553480156200002657600080fd5b50604051620040a3380380620040a383398101604081905262000049916200016e565b6200005433620000eb565b6001600160a01b038216608052600280546001600160a01b031916600117905560005b8151811015620000e25760018060008484815181106200009b576200009b62000257565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000d9816200026d565b91505062000077565b50505062000297565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200015357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200018257600080fd5b6200018d836200013b565b602084810151919350906001600160401b0380821115620001ad57600080fd5b818601915086601f830112620001c257600080fd5b815181811115620001d757620001d762000158565b8060051b604051601f19603f83011681018181108582111715620001ff57620001ff62000158565b6040529182528482019250838101850191898311156200021e57600080fd5b938501935b82851015620002475762000237856200013b565b8452938501939285019262000223565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200029057634e487b7160e01b600052601160045260246000fd5b5060010190565b608051613da3620003006000396000818161018d01528181611798015281816127380152818161279d01528181612807015281816128cc0152818161297901528181612a5d01528181612b6401528181612c1001528181612cdf0152612df10152613da36000f3fe6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "deployedBytecode": "0x6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "devdoc": { + "author": "Ilya Lyalin", + "kind": "dev", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IAlgebraPoolActions#swap call" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the PancakeV3Pool#swap call" + } + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "route": "Route to process", + "to": "Where to transfer output tokens", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IUniswapV3PoolActions#swap call" + } + } + }, + "title": "A route processor for the Sushi Aggregator", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IAlgebraPool#swap." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via PancakeV3Pool#swap." + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "notice": "Processes the route generated off-chain. Has a lock" + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value of input tokens to and then processes the route" + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "processes the route and sends amount of output token to " + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value to and then processes the route" + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 1060, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "priviledgedUsers", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 1062, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "lastCalledPool", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 1065, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "unlocked", + "offset": 20, + "slot": "2", + "type": "t_uint8" + }, + { + "astId": 1068, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "paused", + "offset": 21, + "slot": "2", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/boba/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json b/protocols/route-processor/deployments/boba/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json new file mode 100644 index 0000000000..01826e7b93 --- /dev/null +++ b/protocols/route-processor/deployments/boba/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json @@ -0,0 +1,80 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" + }, + "contracts/InputStream.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" + }, + "contracts/RouteProcessor5.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" + }, + "contracts/Utils.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "interfaces/IBentoBoxMinimal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" + }, + "interfaces/ICurve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" + }, + "interfaces/IPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" + }, + "interfaces/ITridentCLPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/bsc/RouteProcessor5.json b/protocols/route-processor/deployments/bsc/RouteProcessor5.json new file mode 100644 index 0000000000..a833a7cf84 --- /dev/null +++ b/protocols/route-processor/deployments/bsc/RouteProcessor5.json @@ -0,0 +1,704 @@ +{ + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_bentoBox", + "type": "address" + }, + { + "internalType": "address[]", + "name": "priviledgedUserList", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "MinimalOutputBalanceViolation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Route", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "algebraSwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bentoBox", + "outputs": [ + { + "internalType": "contract IBentoBoxMinimal", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "pancakeV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "priviledgedUsers", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueInput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "priviledge", + "type": "bool" + } + ], + "name": "setPriviledge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "transferValueAndprocessRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x22660f7b536d8de081cb09f7d66e1b094f64f171fad804d44723e9080dd765e8", + "receipt": { + "to": null, + "from": "0x282607716D9B4fDD0B094d5864fac56313f5e665", + "contractAddress": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "transactionIndex": 1, + "gasUsed": "3489875", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000020000000000000000000000000000000000000001000000000000000000000000000000000000000000040000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000000000000000000000000000", + "blockHash": "0x99f53ae4659faa558df2886d156425b586914e8498ff67623f7789b0a1b096fc", + "transactionHash": "0x22660f7b536d8de081cb09f7d66e1b094f64f171fad804d44723e9080dd765e8", + "logs": [ + { + "transactionIndex": 1, + "blockNumber": 40891599, + "transactionHash": "0x22660f7b536d8de081cb09f7d66e1b094f64f171fad804d44723e9080dd765e8", + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000282607716d9b4fdd0b094d5864fac56313f5e665" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0x99f53ae4659faa558df2886d156425b586914e8498ff67623f7789b0a1b096fc" + } + ], + "blockNumber": 40891599, + "cumulativeGasUsed": "3512155", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000000", + [] + ], + "numDeployments": 1, + "solcInputHash": "e556d43a3caf4f1fb4f12d632d103b28", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bentoBox\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"priviledgedUserList\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"MinimalOutputBalanceViolation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"Route\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"algebraSwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"pancakeV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"priviledgedUsers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"priviledge\",\"type\":\"bool\"}],\"name\":\"setPriviledge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"transferValueAndprocessRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"Ilya Lyalin\",\"kind\":\"dev\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IAlgebraPoolActions#swap call\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the PancakeV3Pool#swap call\"}},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"route\":\"Route to process\",\"to\":\"Where to transfer output tokens\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IUniswapV3PoolActions#swap call\"}}},\"title\":\"A route processor for the Sushi Aggregator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\"},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Processes the route generated off-chain. Has a lock\"},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value of input tokens to and then processes the route\"},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"processes the route and sends amount of output token to \"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value to and then processes the route\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RouteProcessor5.sol\":\"RouteProcessor5\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\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 Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.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 function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\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\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\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 * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\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\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/InputStream.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\n/** @notice Simple read stream */\\nlibrary InputStream {\\n\\n /** @notice Creates stream from data\\n * @param data data\\n */\\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\\n assembly {\\n stream := mload(0x40)\\n mstore(0x40, add(stream, 64))\\n mstore(stream, data)\\n let length := mload(data)\\n mstore(add(stream, 32), add(data, length))\\n }\\n }\\n\\n /** @notice Checks if stream is not empty\\n * @param stream stream\\n */\\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\\n uint256 pos;\\n uint256 finish;\\n assembly {\\n pos := mload(stream)\\n finish := mload(add(stream, 32))\\n }\\n return pos < finish;\\n }\\n\\n /** @notice Reads uint8 from the stream\\n * @param stream stream\\n */\\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 1)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint16 from the stream\\n * @param stream stream\\n */\\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 2)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint24 from the stream\\n * @param stream stream\\n */\\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 3)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint32 from the stream\\n * @param stream stream\\n */\\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 4)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint256 from the stream\\n * @param stream stream\\n */\\n function readUint(uint256 stream) internal pure returns (uint256 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes32 from the stream\\n * @param stream stream\\n */\\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads address from the stream\\n * @param stream stream\\n */\\n function readAddress(uint256 stream) internal pure returns (address res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 20)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes from the stream\\n * @param stream stream\\n */\\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\\n assembly {\\n let pos := mload(stream)\\n res := add(pos, 32)\\n let length := mload(res)\\n mstore(stream, add(res, length))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x24e24bd0e49cbddacbf3b26bcd4bdffac63d11f3259bc05bc93c0835e8ff5300\",\"license\":\"UNLICENSED\"},\"contracts/RouteProcessor5.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '../interfaces/IUniswapV2Pair.sol';\\nimport '../interfaces/IUniswapV3Pool.sol';\\nimport '../interfaces/ITridentCLPool.sol';\\nimport '../interfaces/IBentoBoxMinimal.sol';\\nimport '../interfaces/IPool.sol';\\nimport '../interfaces/IWETH.sol';\\nimport '../interfaces/ICurve.sol';\\nimport './InputStream.sol';\\nimport './Utils.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\\n\\nuint8 constant LOCKED = 2;\\nuint8 constant NOT_LOCKED = 1;\\nuint8 constant PAUSED = 2;\\nuint8 constant NOT_PAUSED = 1;\\n\\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\nuint160 constant MIN_SQRT_RATIO = 4295128739;\\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n/// @title A route processor for the Sushi Aggregator\\n/// @author Ilya Lyalin\\ncontract RouteProcessor5 is Ownable {\\n using SafeERC20 for IERC20;\\n using Utils for IERC20;\\n using Utils for address;\\n using SafeERC20 for IERC20Permit;\\n using InputStream for uint256;\\n\\n event Route(\\n address indexed from, \\n address to, \\n address indexed tokenIn, \\n address indexed tokenOut, \\n uint256 amountIn, \\n uint256 amountOutMin,\\n uint256 amountOut\\n );\\n\\n error MinimalOutputBalanceViolation(uint256 amountOut);\\n\\n IBentoBoxMinimal public immutable bentoBox;\\n mapping (address => bool) public priviledgedUsers;\\n address private lastCalledPool;\\n\\n uint8 private unlocked = NOT_LOCKED;\\n uint8 private paused = NOT_PAUSED;\\n modifier lock() {\\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\\n unlocked = LOCKED;\\n _;\\n unlocked = NOT_LOCKED;\\n }\\n\\n modifier onlyOwnerOrPriviledgedUser() {\\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \\\"RP: caller is not the owner or a privileged user\\\");\\n _;\\n }\\n\\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\\n bentoBox = IBentoBoxMinimal(_bentoBox);\\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n\\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\\n priviledgedUsers[priviledgedUserList[i]] = true;\\n }\\n }\\n\\n function setPriviledge(address user, bool priviledge) external onlyOwner {\\n priviledgedUsers[user] = priviledge;\\n }\\n\\n function pause() external onlyOwnerOrPriviledgedUser {\\n paused = PAUSED;\\n }\\n\\n function resume() external onlyOwnerOrPriviledgedUser {\\n paused = NOT_PAUSED;\\n }\\n\\n /// @notice For native unwrapping\\n receive() external payable {}\\n\\n /// @notice Processes the route generated off-chain. Has a lock\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @param to Where to transfer output tokens\\n /// @param route Route to process\\n /// @return amountOut Actual amount of the output token\\n function processRoute(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function transferValueAndprocessRoute(\\n address transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n transferValueTo.transferNative(amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value of input tokens to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueInput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n \\n /// @notice processes the route and sends amount of output token to \\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueOutput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\\n }\\n\\n /// @notice Processes the route generated off-chain\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteInternal(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) private returns (uint256 amountOut) {\\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\\n\\n uint256 realAmountIn = amountIn;\\n {\\n uint256 step = 0;\\n uint256 stream = InputStream.createStream(route);\\n while (stream.isNotEmpty()) {\\n uint8 commandCode = stream.readUint8();\\n if (commandCode == 1) {\\n uint256 usedAmount = processMyERC20(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 2) processUserERC20(stream, amountIn);\\n else if (commandCode == 3) {\\n uint256 usedAmount = processNative(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 4) processOnePool(stream);\\n else if (commandCode == 5) processInsideBento(stream);\\n else if (commandCode == 6) applyPermit(tokenIn, stream);\\n else revert('RouteProcessor: Unknown command code');\\n ++step;\\n }\\n }\\n\\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\\n if (tokenIn != Utils.NATIVE_ADDRESS)\\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\\n \\n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\\n\\n amountOut = balanceOutFinal - balanceOutInitial;\\n\\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\\n }\\n\\n /// @notice Applies ERC-2612 permit\\n /// @param tokenIn permitted token\\n /// @param stream Streamed program\\n function applyPermit(address tokenIn, uint256 stream) private {\\n uint256 value = stream.readUint();\\n uint256 deadline = stream.readUint();\\n uint8 v = stream.readUint8();\\n bytes32 r = stream.readBytes32();\\n bytes32 s = stream.readBytes32();\\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\\n }\\n }\\n\\n /// @notice Processes native coin: call swap for all pools that swap from native coin\\n /// @param stream Streamed program\\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\\n amountTotal = address(this).balance;\\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token from this contract balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\\n address token = stream.readAddress();\\n amountTotal = IERC20(token).balanceOf(address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n \\n /// @notice Processes ERC20 token from msg.sender balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n /// @param amountTotal Amount of tokens to take from msg.sender\\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\\n address token = stream.readAddress();\\n distributeAndSwap(stream, msg.sender, token, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token for cases when the token has only one output pool\\n /// @notice In this case liquidity is already at pool balance. This is an optimization\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processOnePool(uint256 stream) private {\\n address token = stream.readAddress();\\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\\n }\\n\\n /// @notice Processes Bento tokens \\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processInsideBento(uint256 stream) private {\\n address token = stream.readAddress();\\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n\\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountTotal Total amount of tokenIn for swaps \\n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\\n uint8 num = stream.readUint8();\\n unchecked {\\n for (uint256 i = 0; i < num; ++i) {\\n uint16 share = stream.readUint16();\\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\\n amountTotal -= amount;\\n swap(stream, from, tokenIn, amount);\\n }\\n }\\n }\\n\\n /// @notice Makes swap\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 poolType = stream.readUint8();\\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\\n else revert('RouteProcessor: Unknown pool type');\\n }\\n\\n /// @notice Wraps/unwraps native token\\n /// @param stream [direction & fake, recipient, wrapToken?]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 directionAndFake = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (directionAndFake & 1 == 1) { // wrap native\\n address wrapToken = stream.readAddress();\\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\\n } else { // unwrap native\\n if (directionAndFake & 2 == 0) {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IWETH(tokenIn).withdraw(amountIn);\\n }\\n to.transferNative(amountIn);\\n }\\n }\\n\\n /// @notice Bridge/unbridge tokens to/from Bento\\n /// @param stream [direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (direction > 0) { // outside to Bento\\n // deposit to arbitrary recipient is possible only from address(bentoBox)\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\\n else {\\n // tokens already are at address(bentoBox)\\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\\n bentoBox.strategyData(tokenIn).balance -\\n bentoBox.totals(tokenIn).elastic;\\n }\\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\\n } else { // Bento to outside\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\\n }\\n }\\n\\n /// @notice UniswapV2 pool swap\\n /// @param stream [pool, direction, recipient, fee]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\\n\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\\n\\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\\n\\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\\n }\\n\\n /// @notice Trident pool swap\\n /// @param stream [pool, swapData]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bytes memory swapData = stream.readBytes();\\n\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, pool, amountIn);\\n }\\n \\n IPool(pool).swap(swapData);\\n }\\n\\n /// @notice UniswapV3 pool swap\\n /// @param stream [pool, direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bool zeroForOne = stream.readUint8() > 0;\\n address recipient = stream.readAddress();\\n\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\\n\\n lastCalledPool = pool;\\n IUniswapV3Pool(pool).swap(\\n recipient,\\n zeroForOne,\\n int256(amountIn),\\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\\n abi.encode(tokenIn)\\n );\\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) public {\\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\\n \\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n (address tokenIn) = abi.decode(data, (address));\\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\\n function algebraSwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\\n function pancakeV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 poolType = stream.readUint8();\\n int128 fromIndex = int8(stream.readUint8());\\n int128 toIndex = int8(stream.readUint8());\\n address to = stream.readAddress();\\n address tokenOut = stream.readAddress();\\n\\n uint256 amountOut;\\n if (tokenIn == Utils.NATIVE_ADDRESS) {\\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\\n } else {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IERC20(tokenIn).approveSafe(pool, amountIn);\\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n else {\\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\\n amountOut = balanceAfter - balanceBefore;\\n }\\n }\\n\\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\\n }\\n}\\n\",\"keccak256\":\"0xcd53a7f473f1847d44c42777a194203cbff02b8c761cb2935402401f57c918a2\",\"license\":\"UNLICENSED\"},\"contracts/Utils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\n\\nlibrary Utils {\\n using SafeERC20 for IERC20;\\n\\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n /**\\n * @dev returns user's balance of token (or native)\\n */\\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\\n if (token == NATIVE_ADDRESS) return address(user).balance;\\n else return IERC20(token).balanceOf(user);\\n }\\n\\n /**\\n * @dev transfers native with correct revert bubble up\\n */\\n function transferNative(address to, uint256 amount) internal {\\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\\n if (!success) {\\n assembly {\\n revert(add(32, returnBytes), mload(returnBytes))\\n }\\n }\\n }\\n\\n /**\\n * @dev transfers ERC20 or native\\n */\\n function transferAny(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\\n else IERC20(token).safeTransfer(to, amount);\\n }\\n\\n /**\\n * @dev transfers from ERC20 or transfers native\\n */\\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n (bool success, bytes memory data) = address(token).call(\\n abi.encodeWithSelector(token.approve.selector, spender, amount)\\n );\\n return success && (data.length == 0 || abi.decode(data, (bool)));\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \\n * current allowance are not zero simultaniously (USDT for example). \\n * In second case it tries to set allowance to 0, and then back to amount.\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n return approveStable(token, spender, amount) \\n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\\n }\\n}\\n\",\"keccak256\":\"0x8c8439edc00b403abd3f34be75a06b1fe71152644ae9f19488af596bbc534ffe\",\"license\":\"UNLICENSED\"},\"interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\nstruct StrategyData {\\n uint64 strategyStartDate;\\n uint64 targetPercentage;\\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n function strategyData(address token) external view returns (StrategyData memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0x0c12eba7a5b9d22d37ab8883fe22d6a312a90682809dbd11c43f8e6ceaff73bf\",\"license\":\"UNLICENSED\"},\"interfaces/ICurve.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\ninterface ICurve {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\\n}\\n\\ninterface ICurveLegacy {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\\n}\\n\\n\",\"keccak256\":\"0x3d4940b3583e06dde20f12e92d2f6ac573b3f64bdaa1e8f480656a3763852518\",\"license\":\"UNLICENSED\"},\"interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/ITridentCLPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface ITridentCLPool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bool unwrapBento,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x572376b80c86a94692b0e27e6e63790b763295e32ba1f956c1d331fc1296de8d\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IUniswapV2Pair.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Pair {\\n event Approval(address indexed owner, address indexed spender, uint value);\\n event Transfer(address indexed from, address indexed to, uint value);\\n\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function allowance(address owner, address spender) external view returns (uint);\\n\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address to, uint value) external returns (bool);\\n function transferFrom(address from, address to, uint value) external returns (bool);\\n\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n function nonces(address owner) external view returns (uint);\\n\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n event Mint(address indexed sender, uint amount0, uint amount1);\\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\\n event Swap(\\n address indexed sender,\\n uint amount0In,\\n uint amount1In,\\n uint amount0Out,\\n uint amount1Out,\\n address indexed to\\n );\\n event Sync(uint112 reserve0, uint112 reserve1);\\n\\n function MINIMUM_LIQUIDITY() external pure returns (uint);\\n function factory() external view returns (address);\\n function token0() external view returns (address);\\n function token1() external view returns (address);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\\n function price0CumulativeLast() external view returns (uint);\\n function price1CumulativeLast() external view returns (uint);\\n function kLast() external view returns (uint);\\n\\n function mint(address to) external returns (uint liquidity);\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function skim(address to) external;\\n function sync() external;\\n\\n function initialize(address, address) external;\\n}\",\"keccak256\":\"0x08f9a63b34855eec941be8d36a04424f1a1725a2c030373fcef3afeb480ca385\",\"license\":\"GPL-3.0\"},\"interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IUniswapV3Pool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x2a4d7c6120e613f0e95d4dc8c650efb9b59e3c25c64e3e5c0a379281500f0a79\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IWETH.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0xae8529ae159f784b90fdcd0629bd03bf7b68accc81edccac53357ad08406a378\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}", + "bytecode": "0x60a06040526002805461ffff60a01b191661010160a01b1790553480156200002657600080fd5b50604051620040a3380380620040a383398101604081905262000049916200016e565b6200005433620000eb565b6001600160a01b038216608052600280546001600160a01b031916600117905560005b8151811015620000e25760018060008484815181106200009b576200009b62000257565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000d9816200026d565b91505062000077565b50505062000297565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200015357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200018257600080fd5b6200018d836200013b565b602084810151919350906001600160401b0380821115620001ad57600080fd5b818601915086601f830112620001c257600080fd5b815181811115620001d757620001d762000158565b8060051b604051601f19603f83011681018181108582111715620001ff57620001ff62000158565b6040529182528482019250838101850191898311156200021e57600080fd5b938501935b82851015620002475762000237856200013b565b8452938501939285019262000223565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200029057634e487b7160e01b600052601160045260246000fd5b5060010190565b608051613da3620003006000396000818161018d01528181611798015281816127380152818161279d01528181612807015281816128cc0152818161297901528181612a5d01528181612b6401528181612c1001528181612cdf0152612df10152613da36000f3fe6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "deployedBytecode": "0x6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "devdoc": { + "author": "Ilya Lyalin", + "kind": "dev", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IAlgebraPoolActions#swap call" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the PancakeV3Pool#swap call" + } + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "route": "Route to process", + "to": "Where to transfer output tokens", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IUniswapV3PoolActions#swap call" + } + } + }, + "title": "A route processor for the Sushi Aggregator", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IAlgebraPool#swap." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via PancakeV3Pool#swap." + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "notice": "Processes the route generated off-chain. Has a lock" + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value of input tokens to and then processes the route" + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "processes the route and sends amount of output token to " + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value to and then processes the route" + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 1060, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "priviledgedUsers", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 1062, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "lastCalledPool", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 1065, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "unlocked", + "offset": 20, + "slot": "2", + "type": "t_uint8" + }, + { + "astId": 1068, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "paused", + "offset": 21, + "slot": "2", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/bsc/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json b/protocols/route-processor/deployments/bsc/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json new file mode 100644 index 0000000000..01826e7b93 --- /dev/null +++ b/protocols/route-processor/deployments/bsc/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json @@ -0,0 +1,80 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" + }, + "contracts/InputStream.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" + }, + "contracts/RouteProcessor5.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" + }, + "contracts/Utils.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "interfaces/IBentoBoxMinimal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" + }, + "interfaces/ICurve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" + }, + "interfaces/IPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" + }, + "interfaces/ITridentCLPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/bttc/RouteProcessor5.json b/protocols/route-processor/deployments/bttc/RouteProcessor5.json new file mode 100644 index 0000000000..cc5b848424 --- /dev/null +++ b/protocols/route-processor/deployments/bttc/RouteProcessor5.json @@ -0,0 +1,719 @@ +{ + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_bentoBox", + "type": "address" + }, + { + "internalType": "address[]", + "name": "priviledgedUserList", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "MinimalOutputBalanceViolation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Route", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "algebraSwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bentoBox", + "outputs": [ + { + "internalType": "contract IBentoBoxMinimal", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "pancakeV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "priviledgedUsers", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueInput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "priviledge", + "type": "bool" + } + ], + "name": "setPriviledge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "transferValueAndprocessRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0xbec54e11e8739747f5e949079cd03d6c09ae2380b461685abf2b77f9fea2ac9b", + "receipt": { + "to": null, + "from": "0x282607716D9B4fDD0B094d5864fac56313f5e665", + "contractAddress": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "transactionIndex": 0, + "gasUsed": "3488833", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800010000000000000020000000000000000000000000000008000000001000000000000000000000000000000000000000000040002800001000000000000000100000000000000000000020000000000000000000800000000000000000080000000000000400000000000000000000000000000000000000000002000000000000000000000200000000000000000000000000000004000000000000000000000000000004000000000000002000001000000000000000000000000000000100000000020000000000000040000000000000000000000000000000000000000000000100000", + "blockHash": "0x8950cac082e4cfc2c69a05fa1e976ee00b7f0e7b30e889c0b71c7f917d97cbed", + "transactionHash": "0xbec54e11e8739747f5e949079cd03d6c09ae2380b461685abf2b77f9fea2ac9b", + "logs": [ + { + "transactionIndex": 0, + "blockNumber": 40276107, + "transactionHash": "0xbec54e11e8739747f5e949079cd03d6c09ae2380b461685abf2b77f9fea2ac9b", + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000282607716d9b4fdd0b094d5864fac56313f5e665" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0x8950cac082e4cfc2c69a05fa1e976ee00b7f0e7b30e889c0b71c7f917d97cbed" + }, + { + "transactionIndex": 0, + "blockNumber": 40276107, + "transactionHash": "0xbec54e11e8739747f5e949079cd03d6c09ae2380b461685abf2b77f9fea2ac9b", + "address": "0x0000000000000000000000000000000000001010", + "topics": [ + "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63", + "0x0000000000000000000000000000000000000000000000000000000000001010", + "0x000000000000000000000000282607716d9b4fdd0b094d5864fac56313f5e665", + "0x000000000000000000000000f5094a6c2f33d9b218d3dc386323695c51f0df79" + ], + "data": "0x00000000000000000000000000000000000000000000005e90a45c6f6e33400000000000000000000000000000000000000000000000007aef3a787e451c80000000000000000000000000000000000000000000036c85485ce4fa01f4f0491900000000000000000000000000000000000000000000001c5e961c0ed6e940000000000000000000000000000000000000000000036c85a6ed89567163238919", + "logIndex": 1, + "blockHash": "0x8950cac082e4cfc2c69a05fa1e976ee00b7f0e7b30e889c0b71c7f917d97cbed" + } + ], + "blockNumber": 40276107, + "cumulativeGasUsed": "3488833", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000000", + [] + ], + "numDeployments": 1, + "solcInputHash": "e556d43a3caf4f1fb4f12d632d103b28", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bentoBox\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"priviledgedUserList\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"MinimalOutputBalanceViolation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"Route\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"algebraSwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"pancakeV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"priviledgedUsers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"priviledge\",\"type\":\"bool\"}],\"name\":\"setPriviledge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"transferValueAndprocessRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"Ilya Lyalin\",\"kind\":\"dev\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IAlgebraPoolActions#swap call\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the PancakeV3Pool#swap call\"}},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"route\":\"Route to process\",\"to\":\"Where to transfer output tokens\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IUniswapV3PoolActions#swap call\"}}},\"title\":\"A route processor for the Sushi Aggregator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\"},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Processes the route generated off-chain. Has a lock\"},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value of input tokens to and then processes the route\"},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"processes the route and sends amount of output token to \"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value to and then processes the route\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RouteProcessor5.sol\":\"RouteProcessor5\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\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 Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.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 function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\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\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\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 * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\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\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/InputStream.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\n/** @notice Simple read stream */\\nlibrary InputStream {\\n\\n /** @notice Creates stream from data\\n * @param data data\\n */\\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\\n assembly {\\n stream := mload(0x40)\\n mstore(0x40, add(stream, 64))\\n mstore(stream, data)\\n let length := mload(data)\\n mstore(add(stream, 32), add(data, length))\\n }\\n }\\n\\n /** @notice Checks if stream is not empty\\n * @param stream stream\\n */\\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\\n uint256 pos;\\n uint256 finish;\\n assembly {\\n pos := mload(stream)\\n finish := mload(add(stream, 32))\\n }\\n return pos < finish;\\n }\\n\\n /** @notice Reads uint8 from the stream\\n * @param stream stream\\n */\\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 1)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint16 from the stream\\n * @param stream stream\\n */\\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 2)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint24 from the stream\\n * @param stream stream\\n */\\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 3)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint32 from the stream\\n * @param stream stream\\n */\\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 4)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint256 from the stream\\n * @param stream stream\\n */\\n function readUint(uint256 stream) internal pure returns (uint256 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes32 from the stream\\n * @param stream stream\\n */\\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads address from the stream\\n * @param stream stream\\n */\\n function readAddress(uint256 stream) internal pure returns (address res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 20)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes from the stream\\n * @param stream stream\\n */\\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\\n assembly {\\n let pos := mload(stream)\\n res := add(pos, 32)\\n let length := mload(res)\\n mstore(stream, add(res, length))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x24e24bd0e49cbddacbf3b26bcd4bdffac63d11f3259bc05bc93c0835e8ff5300\",\"license\":\"UNLICENSED\"},\"contracts/RouteProcessor5.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '../interfaces/IUniswapV2Pair.sol';\\nimport '../interfaces/IUniswapV3Pool.sol';\\nimport '../interfaces/ITridentCLPool.sol';\\nimport '../interfaces/IBentoBoxMinimal.sol';\\nimport '../interfaces/IPool.sol';\\nimport '../interfaces/IWETH.sol';\\nimport '../interfaces/ICurve.sol';\\nimport './InputStream.sol';\\nimport './Utils.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\\n\\nuint8 constant LOCKED = 2;\\nuint8 constant NOT_LOCKED = 1;\\nuint8 constant PAUSED = 2;\\nuint8 constant NOT_PAUSED = 1;\\n\\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\nuint160 constant MIN_SQRT_RATIO = 4295128739;\\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n/// @title A route processor for the Sushi Aggregator\\n/// @author Ilya Lyalin\\ncontract RouteProcessor5 is Ownable {\\n using SafeERC20 for IERC20;\\n using Utils for IERC20;\\n using Utils for address;\\n using SafeERC20 for IERC20Permit;\\n using InputStream for uint256;\\n\\n event Route(\\n address indexed from, \\n address to, \\n address indexed tokenIn, \\n address indexed tokenOut, \\n uint256 amountIn, \\n uint256 amountOutMin,\\n uint256 amountOut\\n );\\n\\n error MinimalOutputBalanceViolation(uint256 amountOut);\\n\\n IBentoBoxMinimal public immutable bentoBox;\\n mapping (address => bool) public priviledgedUsers;\\n address private lastCalledPool;\\n\\n uint8 private unlocked = NOT_LOCKED;\\n uint8 private paused = NOT_PAUSED;\\n modifier lock() {\\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\\n unlocked = LOCKED;\\n _;\\n unlocked = NOT_LOCKED;\\n }\\n\\n modifier onlyOwnerOrPriviledgedUser() {\\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \\\"RP: caller is not the owner or a privileged user\\\");\\n _;\\n }\\n\\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\\n bentoBox = IBentoBoxMinimal(_bentoBox);\\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n\\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\\n priviledgedUsers[priviledgedUserList[i]] = true;\\n }\\n }\\n\\n function setPriviledge(address user, bool priviledge) external onlyOwner {\\n priviledgedUsers[user] = priviledge;\\n }\\n\\n function pause() external onlyOwnerOrPriviledgedUser {\\n paused = PAUSED;\\n }\\n\\n function resume() external onlyOwnerOrPriviledgedUser {\\n paused = NOT_PAUSED;\\n }\\n\\n /// @notice For native unwrapping\\n receive() external payable {}\\n\\n /// @notice Processes the route generated off-chain. Has a lock\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @param to Where to transfer output tokens\\n /// @param route Route to process\\n /// @return amountOut Actual amount of the output token\\n function processRoute(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function transferValueAndprocessRoute(\\n address transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n transferValueTo.transferNative(amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value of input tokens to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueInput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n \\n /// @notice processes the route and sends amount of output token to \\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueOutput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\\n }\\n\\n /// @notice Processes the route generated off-chain\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteInternal(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) private returns (uint256 amountOut) {\\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\\n\\n uint256 realAmountIn = amountIn;\\n {\\n uint256 step = 0;\\n uint256 stream = InputStream.createStream(route);\\n while (stream.isNotEmpty()) {\\n uint8 commandCode = stream.readUint8();\\n if (commandCode == 1) {\\n uint256 usedAmount = processMyERC20(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 2) processUserERC20(stream, amountIn);\\n else if (commandCode == 3) {\\n uint256 usedAmount = processNative(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 4) processOnePool(stream);\\n else if (commandCode == 5) processInsideBento(stream);\\n else if (commandCode == 6) applyPermit(tokenIn, stream);\\n else revert('RouteProcessor: Unknown command code');\\n ++step;\\n }\\n }\\n\\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\\n if (tokenIn != Utils.NATIVE_ADDRESS)\\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\\n \\n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\\n\\n amountOut = balanceOutFinal - balanceOutInitial;\\n\\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\\n }\\n\\n /// @notice Applies ERC-2612 permit\\n /// @param tokenIn permitted token\\n /// @param stream Streamed program\\n function applyPermit(address tokenIn, uint256 stream) private {\\n uint256 value = stream.readUint();\\n uint256 deadline = stream.readUint();\\n uint8 v = stream.readUint8();\\n bytes32 r = stream.readBytes32();\\n bytes32 s = stream.readBytes32();\\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\\n }\\n }\\n\\n /// @notice Processes native coin: call swap for all pools that swap from native coin\\n /// @param stream Streamed program\\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\\n amountTotal = address(this).balance;\\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token from this contract balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\\n address token = stream.readAddress();\\n amountTotal = IERC20(token).balanceOf(address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n \\n /// @notice Processes ERC20 token from msg.sender balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n /// @param amountTotal Amount of tokens to take from msg.sender\\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\\n address token = stream.readAddress();\\n distributeAndSwap(stream, msg.sender, token, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token for cases when the token has only one output pool\\n /// @notice In this case liquidity is already at pool balance. This is an optimization\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processOnePool(uint256 stream) private {\\n address token = stream.readAddress();\\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\\n }\\n\\n /// @notice Processes Bento tokens \\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processInsideBento(uint256 stream) private {\\n address token = stream.readAddress();\\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n\\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountTotal Total amount of tokenIn for swaps \\n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\\n uint8 num = stream.readUint8();\\n unchecked {\\n for (uint256 i = 0; i < num; ++i) {\\n uint16 share = stream.readUint16();\\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\\n amountTotal -= amount;\\n swap(stream, from, tokenIn, amount);\\n }\\n }\\n }\\n\\n /// @notice Makes swap\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 poolType = stream.readUint8();\\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\\n else revert('RouteProcessor: Unknown pool type');\\n }\\n\\n /// @notice Wraps/unwraps native token\\n /// @param stream [direction & fake, recipient, wrapToken?]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 directionAndFake = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (directionAndFake & 1 == 1) { // wrap native\\n address wrapToken = stream.readAddress();\\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\\n } else { // unwrap native\\n if (directionAndFake & 2 == 0) {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IWETH(tokenIn).withdraw(amountIn);\\n }\\n to.transferNative(amountIn);\\n }\\n }\\n\\n /// @notice Bridge/unbridge tokens to/from Bento\\n /// @param stream [direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (direction > 0) { // outside to Bento\\n // deposit to arbitrary recipient is possible only from address(bentoBox)\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\\n else {\\n // tokens already are at address(bentoBox)\\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\\n bentoBox.strategyData(tokenIn).balance -\\n bentoBox.totals(tokenIn).elastic;\\n }\\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\\n } else { // Bento to outside\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\\n }\\n }\\n\\n /// @notice UniswapV2 pool swap\\n /// @param stream [pool, direction, recipient, fee]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\\n\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\\n\\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\\n\\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\\n }\\n\\n /// @notice Trident pool swap\\n /// @param stream [pool, swapData]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bytes memory swapData = stream.readBytes();\\n\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, pool, amountIn);\\n }\\n \\n IPool(pool).swap(swapData);\\n }\\n\\n /// @notice UniswapV3 pool swap\\n /// @param stream [pool, direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bool zeroForOne = stream.readUint8() > 0;\\n address recipient = stream.readAddress();\\n\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\\n\\n lastCalledPool = pool;\\n IUniswapV3Pool(pool).swap(\\n recipient,\\n zeroForOne,\\n int256(amountIn),\\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\\n abi.encode(tokenIn)\\n );\\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) public {\\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\\n \\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n (address tokenIn) = abi.decode(data, (address));\\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\\n function algebraSwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\\n function pancakeV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 poolType = stream.readUint8();\\n int128 fromIndex = int8(stream.readUint8());\\n int128 toIndex = int8(stream.readUint8());\\n address to = stream.readAddress();\\n address tokenOut = stream.readAddress();\\n\\n uint256 amountOut;\\n if (tokenIn == Utils.NATIVE_ADDRESS) {\\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\\n } else {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IERC20(tokenIn).approveSafe(pool, amountIn);\\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n else {\\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\\n amountOut = balanceAfter - balanceBefore;\\n }\\n }\\n\\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\\n }\\n}\\n\",\"keccak256\":\"0xcd53a7f473f1847d44c42777a194203cbff02b8c761cb2935402401f57c918a2\",\"license\":\"UNLICENSED\"},\"contracts/Utils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\n\\nlibrary Utils {\\n using SafeERC20 for IERC20;\\n\\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n /**\\n * @dev returns user's balance of token (or native)\\n */\\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\\n if (token == NATIVE_ADDRESS) return address(user).balance;\\n else return IERC20(token).balanceOf(user);\\n }\\n\\n /**\\n * @dev transfers native with correct revert bubble up\\n */\\n function transferNative(address to, uint256 amount) internal {\\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\\n if (!success) {\\n assembly {\\n revert(add(32, returnBytes), mload(returnBytes))\\n }\\n }\\n }\\n\\n /**\\n * @dev transfers ERC20 or native\\n */\\n function transferAny(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\\n else IERC20(token).safeTransfer(to, amount);\\n }\\n\\n /**\\n * @dev transfers from ERC20 or transfers native\\n */\\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n (bool success, bytes memory data) = address(token).call(\\n abi.encodeWithSelector(token.approve.selector, spender, amount)\\n );\\n return success && (data.length == 0 || abi.decode(data, (bool)));\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \\n * current allowance are not zero simultaniously (USDT for example). \\n * In second case it tries to set allowance to 0, and then back to amount.\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n return approveStable(token, spender, amount) \\n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\\n }\\n}\\n\",\"keccak256\":\"0x8c8439edc00b403abd3f34be75a06b1fe71152644ae9f19488af596bbc534ffe\",\"license\":\"UNLICENSED\"},\"interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\nstruct StrategyData {\\n uint64 strategyStartDate;\\n uint64 targetPercentage;\\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n function strategyData(address token) external view returns (StrategyData memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0x0c12eba7a5b9d22d37ab8883fe22d6a312a90682809dbd11c43f8e6ceaff73bf\",\"license\":\"UNLICENSED\"},\"interfaces/ICurve.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\ninterface ICurve {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\\n}\\n\\ninterface ICurveLegacy {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\\n}\\n\\n\",\"keccak256\":\"0x3d4940b3583e06dde20f12e92d2f6ac573b3f64bdaa1e8f480656a3763852518\",\"license\":\"UNLICENSED\"},\"interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/ITridentCLPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface ITridentCLPool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bool unwrapBento,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x572376b80c86a94692b0e27e6e63790b763295e32ba1f956c1d331fc1296de8d\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IUniswapV2Pair.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Pair {\\n event Approval(address indexed owner, address indexed spender, uint value);\\n event Transfer(address indexed from, address indexed to, uint value);\\n\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function allowance(address owner, address spender) external view returns (uint);\\n\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address to, uint value) external returns (bool);\\n function transferFrom(address from, address to, uint value) external returns (bool);\\n\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n function nonces(address owner) external view returns (uint);\\n\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n event Mint(address indexed sender, uint amount0, uint amount1);\\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\\n event Swap(\\n address indexed sender,\\n uint amount0In,\\n uint amount1In,\\n uint amount0Out,\\n uint amount1Out,\\n address indexed to\\n );\\n event Sync(uint112 reserve0, uint112 reserve1);\\n\\n function MINIMUM_LIQUIDITY() external pure returns (uint);\\n function factory() external view returns (address);\\n function token0() external view returns (address);\\n function token1() external view returns (address);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\\n function price0CumulativeLast() external view returns (uint);\\n function price1CumulativeLast() external view returns (uint);\\n function kLast() external view returns (uint);\\n\\n function mint(address to) external returns (uint liquidity);\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function skim(address to) external;\\n function sync() external;\\n\\n function initialize(address, address) external;\\n}\",\"keccak256\":\"0x08f9a63b34855eec941be8d36a04424f1a1725a2c030373fcef3afeb480ca385\",\"license\":\"GPL-3.0\"},\"interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IUniswapV3Pool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x2a4d7c6120e613f0e95d4dc8c650efb9b59e3c25c64e3e5c0a379281500f0a79\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IWETH.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0xae8529ae159f784b90fdcd0629bd03bf7b68accc81edccac53357ad08406a378\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}", + "bytecode": "0x60a06040526002805461ffff60a01b191661010160a01b1790553480156200002657600080fd5b50604051620040a3380380620040a383398101604081905262000049916200016e565b6200005433620000eb565b6001600160a01b038216608052600280546001600160a01b031916600117905560005b8151811015620000e25760018060008484815181106200009b576200009b62000257565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000d9816200026d565b91505062000077565b50505062000297565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200015357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200018257600080fd5b6200018d836200013b565b602084810151919350906001600160401b0380821115620001ad57600080fd5b818601915086601f830112620001c257600080fd5b815181811115620001d757620001d762000158565b8060051b604051601f19603f83011681018181108582111715620001ff57620001ff62000158565b6040529182528482019250838101850191898311156200021e57600080fd5b938501935b82851015620002475762000237856200013b565b8452938501939285019262000223565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200029057634e487b7160e01b600052601160045260246000fd5b5060010190565b608051613da3620003006000396000818161018d01528181611798015281816127380152818161279d01528181612807015281816128cc0152818161297901528181612a5d01528181612b6401528181612c1001528181612cdf0152612df10152613da36000f3fe6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "deployedBytecode": "0x6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "devdoc": { + "author": "Ilya Lyalin", + "kind": "dev", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IAlgebraPoolActions#swap call" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the PancakeV3Pool#swap call" + } + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "route": "Route to process", + "to": "Where to transfer output tokens", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IUniswapV3PoolActions#swap call" + } + } + }, + "title": "A route processor for the Sushi Aggregator", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IAlgebraPool#swap." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via PancakeV3Pool#swap." + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "notice": "Processes the route generated off-chain. Has a lock" + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value of input tokens to and then processes the route" + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "processes the route and sends amount of output token to " + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value to and then processes the route" + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 1060, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "priviledgedUsers", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 1062, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "lastCalledPool", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 1065, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "unlocked", + "offset": 20, + "slot": "2", + "type": "t_uint8" + }, + { + "astId": 1068, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "paused", + "offset": 21, + "slot": "2", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/bttc/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json b/protocols/route-processor/deployments/bttc/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json new file mode 100644 index 0000000000..01826e7b93 --- /dev/null +++ b/protocols/route-processor/deployments/bttc/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json @@ -0,0 +1,80 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" + }, + "contracts/InputStream.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" + }, + "contracts/RouteProcessor5.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" + }, + "contracts/Utils.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "interfaces/IBentoBoxMinimal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" + }, + "interfaces/ICurve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" + }, + "interfaces/IPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" + }, + "interfaces/ITridentCLPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/celo/RouteProcessor5.json b/protocols/route-processor/deployments/celo/RouteProcessor5.json new file mode 100644 index 0000000000..2a59ef1065 --- /dev/null +++ b/protocols/route-processor/deployments/celo/RouteProcessor5.json @@ -0,0 +1,704 @@ +{ + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_bentoBox", + "type": "address" + }, + { + "internalType": "address[]", + "name": "priviledgedUserList", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "MinimalOutputBalanceViolation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Route", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "algebraSwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bentoBox", + "outputs": [ + { + "internalType": "contract IBentoBoxMinimal", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "pancakeV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "priviledgedUsers", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueInput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "priviledge", + "type": "bool" + } + ], + "name": "setPriviledge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "transferValueAndprocessRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x0631af3b5e4a6bbd810c005a37ab258e2a257b6bb2b97a04d94d95084d3c8bf8", + "receipt": { + "to": null, + "from": "0x282607716D9B4fDD0B094d5864fac56313f5e665", + "contractAddress": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "transactionIndex": 0, + "gasUsed": "3488833", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000020000000000000000000000000000000000000001000000000000000000000000000000000000000000040000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000000000000000000000000000", + "blockHash": "0x87627b36b215c8970c0b50ff6266dbdcc433a8dc00b62e024dbb96cc896b0aa2", + "transactionHash": "0x0631af3b5e4a6bbd810c005a37ab258e2a257b6bb2b97a04d94d95084d3c8bf8", + "logs": [ + { + "transactionIndex": 0, + "blockNumber": 26913948, + "transactionHash": "0x0631af3b5e4a6bbd810c005a37ab258e2a257b6bb2b97a04d94d95084d3c8bf8", + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000282607716d9b4fdd0b094d5864fac56313f5e665" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0x87627b36b215c8970c0b50ff6266dbdcc433a8dc00b62e024dbb96cc896b0aa2" + } + ], + "blockNumber": 26913948, + "cumulativeGasUsed": "3488833", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000000", + [] + ], + "numDeployments": 1, + "solcInputHash": "e556d43a3caf4f1fb4f12d632d103b28", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bentoBox\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"priviledgedUserList\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"MinimalOutputBalanceViolation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"Route\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"algebraSwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"pancakeV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"priviledgedUsers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"priviledge\",\"type\":\"bool\"}],\"name\":\"setPriviledge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"transferValueAndprocessRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"Ilya Lyalin\",\"kind\":\"dev\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IAlgebraPoolActions#swap call\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the PancakeV3Pool#swap call\"}},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"route\":\"Route to process\",\"to\":\"Where to transfer output tokens\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IUniswapV3PoolActions#swap call\"}}},\"title\":\"A route processor for the Sushi Aggregator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\"},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Processes the route generated off-chain. Has a lock\"},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value of input tokens to and then processes the route\"},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"processes the route and sends amount of output token to \"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value to and then processes the route\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RouteProcessor5.sol\":\"RouteProcessor5\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\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 Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.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 function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\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\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\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 * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\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\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/InputStream.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\n/** @notice Simple read stream */\\nlibrary InputStream {\\n\\n /** @notice Creates stream from data\\n * @param data data\\n */\\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\\n assembly {\\n stream := mload(0x40)\\n mstore(0x40, add(stream, 64))\\n mstore(stream, data)\\n let length := mload(data)\\n mstore(add(stream, 32), add(data, length))\\n }\\n }\\n\\n /** @notice Checks if stream is not empty\\n * @param stream stream\\n */\\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\\n uint256 pos;\\n uint256 finish;\\n assembly {\\n pos := mload(stream)\\n finish := mload(add(stream, 32))\\n }\\n return pos < finish;\\n }\\n\\n /** @notice Reads uint8 from the stream\\n * @param stream stream\\n */\\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 1)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint16 from the stream\\n * @param stream stream\\n */\\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 2)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint24 from the stream\\n * @param stream stream\\n */\\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 3)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint32 from the stream\\n * @param stream stream\\n */\\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 4)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint256 from the stream\\n * @param stream stream\\n */\\n function readUint(uint256 stream) internal pure returns (uint256 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes32 from the stream\\n * @param stream stream\\n */\\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads address from the stream\\n * @param stream stream\\n */\\n function readAddress(uint256 stream) internal pure returns (address res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 20)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes from the stream\\n * @param stream stream\\n */\\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\\n assembly {\\n let pos := mload(stream)\\n res := add(pos, 32)\\n let length := mload(res)\\n mstore(stream, add(res, length))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x24e24bd0e49cbddacbf3b26bcd4bdffac63d11f3259bc05bc93c0835e8ff5300\",\"license\":\"UNLICENSED\"},\"contracts/RouteProcessor5.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '../interfaces/IUniswapV2Pair.sol';\\nimport '../interfaces/IUniswapV3Pool.sol';\\nimport '../interfaces/ITridentCLPool.sol';\\nimport '../interfaces/IBentoBoxMinimal.sol';\\nimport '../interfaces/IPool.sol';\\nimport '../interfaces/IWETH.sol';\\nimport '../interfaces/ICurve.sol';\\nimport './InputStream.sol';\\nimport './Utils.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\\n\\nuint8 constant LOCKED = 2;\\nuint8 constant NOT_LOCKED = 1;\\nuint8 constant PAUSED = 2;\\nuint8 constant NOT_PAUSED = 1;\\n\\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\nuint160 constant MIN_SQRT_RATIO = 4295128739;\\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n/// @title A route processor for the Sushi Aggregator\\n/// @author Ilya Lyalin\\ncontract RouteProcessor5 is Ownable {\\n using SafeERC20 for IERC20;\\n using Utils for IERC20;\\n using Utils for address;\\n using SafeERC20 for IERC20Permit;\\n using InputStream for uint256;\\n\\n event Route(\\n address indexed from, \\n address to, \\n address indexed tokenIn, \\n address indexed tokenOut, \\n uint256 amountIn, \\n uint256 amountOutMin,\\n uint256 amountOut\\n );\\n\\n error MinimalOutputBalanceViolation(uint256 amountOut);\\n\\n IBentoBoxMinimal public immutable bentoBox;\\n mapping (address => bool) public priviledgedUsers;\\n address private lastCalledPool;\\n\\n uint8 private unlocked = NOT_LOCKED;\\n uint8 private paused = NOT_PAUSED;\\n modifier lock() {\\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\\n unlocked = LOCKED;\\n _;\\n unlocked = NOT_LOCKED;\\n }\\n\\n modifier onlyOwnerOrPriviledgedUser() {\\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \\\"RP: caller is not the owner or a privileged user\\\");\\n _;\\n }\\n\\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\\n bentoBox = IBentoBoxMinimal(_bentoBox);\\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n\\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\\n priviledgedUsers[priviledgedUserList[i]] = true;\\n }\\n }\\n\\n function setPriviledge(address user, bool priviledge) external onlyOwner {\\n priviledgedUsers[user] = priviledge;\\n }\\n\\n function pause() external onlyOwnerOrPriviledgedUser {\\n paused = PAUSED;\\n }\\n\\n function resume() external onlyOwnerOrPriviledgedUser {\\n paused = NOT_PAUSED;\\n }\\n\\n /// @notice For native unwrapping\\n receive() external payable {}\\n\\n /// @notice Processes the route generated off-chain. Has a lock\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @param to Where to transfer output tokens\\n /// @param route Route to process\\n /// @return amountOut Actual amount of the output token\\n function processRoute(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function transferValueAndprocessRoute(\\n address transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n transferValueTo.transferNative(amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value of input tokens to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueInput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n \\n /// @notice processes the route and sends amount of output token to \\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueOutput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\\n }\\n\\n /// @notice Processes the route generated off-chain\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteInternal(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) private returns (uint256 amountOut) {\\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\\n\\n uint256 realAmountIn = amountIn;\\n {\\n uint256 step = 0;\\n uint256 stream = InputStream.createStream(route);\\n while (stream.isNotEmpty()) {\\n uint8 commandCode = stream.readUint8();\\n if (commandCode == 1) {\\n uint256 usedAmount = processMyERC20(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 2) processUserERC20(stream, amountIn);\\n else if (commandCode == 3) {\\n uint256 usedAmount = processNative(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 4) processOnePool(stream);\\n else if (commandCode == 5) processInsideBento(stream);\\n else if (commandCode == 6) applyPermit(tokenIn, stream);\\n else revert('RouteProcessor: Unknown command code');\\n ++step;\\n }\\n }\\n\\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\\n if (tokenIn != Utils.NATIVE_ADDRESS)\\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\\n \\n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\\n\\n amountOut = balanceOutFinal - balanceOutInitial;\\n\\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\\n }\\n\\n /// @notice Applies ERC-2612 permit\\n /// @param tokenIn permitted token\\n /// @param stream Streamed program\\n function applyPermit(address tokenIn, uint256 stream) private {\\n uint256 value = stream.readUint();\\n uint256 deadline = stream.readUint();\\n uint8 v = stream.readUint8();\\n bytes32 r = stream.readBytes32();\\n bytes32 s = stream.readBytes32();\\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\\n }\\n }\\n\\n /// @notice Processes native coin: call swap for all pools that swap from native coin\\n /// @param stream Streamed program\\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\\n amountTotal = address(this).balance;\\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token from this contract balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\\n address token = stream.readAddress();\\n amountTotal = IERC20(token).balanceOf(address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n \\n /// @notice Processes ERC20 token from msg.sender balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n /// @param amountTotal Amount of tokens to take from msg.sender\\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\\n address token = stream.readAddress();\\n distributeAndSwap(stream, msg.sender, token, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token for cases when the token has only one output pool\\n /// @notice In this case liquidity is already at pool balance. This is an optimization\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processOnePool(uint256 stream) private {\\n address token = stream.readAddress();\\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\\n }\\n\\n /// @notice Processes Bento tokens \\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processInsideBento(uint256 stream) private {\\n address token = stream.readAddress();\\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n\\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountTotal Total amount of tokenIn for swaps \\n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\\n uint8 num = stream.readUint8();\\n unchecked {\\n for (uint256 i = 0; i < num; ++i) {\\n uint16 share = stream.readUint16();\\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\\n amountTotal -= amount;\\n swap(stream, from, tokenIn, amount);\\n }\\n }\\n }\\n\\n /// @notice Makes swap\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 poolType = stream.readUint8();\\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\\n else revert('RouteProcessor: Unknown pool type');\\n }\\n\\n /// @notice Wraps/unwraps native token\\n /// @param stream [direction & fake, recipient, wrapToken?]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 directionAndFake = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (directionAndFake & 1 == 1) { // wrap native\\n address wrapToken = stream.readAddress();\\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\\n } else { // unwrap native\\n if (directionAndFake & 2 == 0) {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IWETH(tokenIn).withdraw(amountIn);\\n }\\n to.transferNative(amountIn);\\n }\\n }\\n\\n /// @notice Bridge/unbridge tokens to/from Bento\\n /// @param stream [direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (direction > 0) { // outside to Bento\\n // deposit to arbitrary recipient is possible only from address(bentoBox)\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\\n else {\\n // tokens already are at address(bentoBox)\\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\\n bentoBox.strategyData(tokenIn).balance -\\n bentoBox.totals(tokenIn).elastic;\\n }\\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\\n } else { // Bento to outside\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\\n }\\n }\\n\\n /// @notice UniswapV2 pool swap\\n /// @param stream [pool, direction, recipient, fee]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\\n\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\\n\\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\\n\\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\\n }\\n\\n /// @notice Trident pool swap\\n /// @param stream [pool, swapData]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bytes memory swapData = stream.readBytes();\\n\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, pool, amountIn);\\n }\\n \\n IPool(pool).swap(swapData);\\n }\\n\\n /// @notice UniswapV3 pool swap\\n /// @param stream [pool, direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bool zeroForOne = stream.readUint8() > 0;\\n address recipient = stream.readAddress();\\n\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\\n\\n lastCalledPool = pool;\\n IUniswapV3Pool(pool).swap(\\n recipient,\\n zeroForOne,\\n int256(amountIn),\\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\\n abi.encode(tokenIn)\\n );\\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) public {\\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\\n \\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n (address tokenIn) = abi.decode(data, (address));\\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\\n function algebraSwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\\n function pancakeV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 poolType = stream.readUint8();\\n int128 fromIndex = int8(stream.readUint8());\\n int128 toIndex = int8(stream.readUint8());\\n address to = stream.readAddress();\\n address tokenOut = stream.readAddress();\\n\\n uint256 amountOut;\\n if (tokenIn == Utils.NATIVE_ADDRESS) {\\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\\n } else {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IERC20(tokenIn).approveSafe(pool, amountIn);\\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n else {\\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\\n amountOut = balanceAfter - balanceBefore;\\n }\\n }\\n\\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\\n }\\n}\\n\",\"keccak256\":\"0xcd53a7f473f1847d44c42777a194203cbff02b8c761cb2935402401f57c918a2\",\"license\":\"UNLICENSED\"},\"contracts/Utils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\n\\nlibrary Utils {\\n using SafeERC20 for IERC20;\\n\\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n /**\\n * @dev returns user's balance of token (or native)\\n */\\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\\n if (token == NATIVE_ADDRESS) return address(user).balance;\\n else return IERC20(token).balanceOf(user);\\n }\\n\\n /**\\n * @dev transfers native with correct revert bubble up\\n */\\n function transferNative(address to, uint256 amount) internal {\\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\\n if (!success) {\\n assembly {\\n revert(add(32, returnBytes), mload(returnBytes))\\n }\\n }\\n }\\n\\n /**\\n * @dev transfers ERC20 or native\\n */\\n function transferAny(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\\n else IERC20(token).safeTransfer(to, amount);\\n }\\n\\n /**\\n * @dev transfers from ERC20 or transfers native\\n */\\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n (bool success, bytes memory data) = address(token).call(\\n abi.encodeWithSelector(token.approve.selector, spender, amount)\\n );\\n return success && (data.length == 0 || abi.decode(data, (bool)));\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \\n * current allowance are not zero simultaniously (USDT for example). \\n * In second case it tries to set allowance to 0, and then back to amount.\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n return approveStable(token, spender, amount) \\n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\\n }\\n}\\n\",\"keccak256\":\"0x8c8439edc00b403abd3f34be75a06b1fe71152644ae9f19488af596bbc534ffe\",\"license\":\"UNLICENSED\"},\"interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\nstruct StrategyData {\\n uint64 strategyStartDate;\\n uint64 targetPercentage;\\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n function strategyData(address token) external view returns (StrategyData memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0x0c12eba7a5b9d22d37ab8883fe22d6a312a90682809dbd11c43f8e6ceaff73bf\",\"license\":\"UNLICENSED\"},\"interfaces/ICurve.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\ninterface ICurve {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\\n}\\n\\ninterface ICurveLegacy {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\\n}\\n\\n\",\"keccak256\":\"0x3d4940b3583e06dde20f12e92d2f6ac573b3f64bdaa1e8f480656a3763852518\",\"license\":\"UNLICENSED\"},\"interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/ITridentCLPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface ITridentCLPool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bool unwrapBento,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x572376b80c86a94692b0e27e6e63790b763295e32ba1f956c1d331fc1296de8d\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IUniswapV2Pair.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Pair {\\n event Approval(address indexed owner, address indexed spender, uint value);\\n event Transfer(address indexed from, address indexed to, uint value);\\n\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function allowance(address owner, address spender) external view returns (uint);\\n\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address to, uint value) external returns (bool);\\n function transferFrom(address from, address to, uint value) external returns (bool);\\n\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n function nonces(address owner) external view returns (uint);\\n\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n event Mint(address indexed sender, uint amount0, uint amount1);\\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\\n event Swap(\\n address indexed sender,\\n uint amount0In,\\n uint amount1In,\\n uint amount0Out,\\n uint amount1Out,\\n address indexed to\\n );\\n event Sync(uint112 reserve0, uint112 reserve1);\\n\\n function MINIMUM_LIQUIDITY() external pure returns (uint);\\n function factory() external view returns (address);\\n function token0() external view returns (address);\\n function token1() external view returns (address);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\\n function price0CumulativeLast() external view returns (uint);\\n function price1CumulativeLast() external view returns (uint);\\n function kLast() external view returns (uint);\\n\\n function mint(address to) external returns (uint liquidity);\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function skim(address to) external;\\n function sync() external;\\n\\n function initialize(address, address) external;\\n}\",\"keccak256\":\"0x08f9a63b34855eec941be8d36a04424f1a1725a2c030373fcef3afeb480ca385\",\"license\":\"GPL-3.0\"},\"interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IUniswapV3Pool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x2a4d7c6120e613f0e95d4dc8c650efb9b59e3c25c64e3e5c0a379281500f0a79\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IWETH.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0xae8529ae159f784b90fdcd0629bd03bf7b68accc81edccac53357ad08406a378\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}", + "bytecode": "0x60a06040526002805461ffff60a01b191661010160a01b1790553480156200002657600080fd5b50604051620040a3380380620040a383398101604081905262000049916200016e565b6200005433620000eb565b6001600160a01b038216608052600280546001600160a01b031916600117905560005b8151811015620000e25760018060008484815181106200009b576200009b62000257565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000d9816200026d565b91505062000077565b50505062000297565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200015357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200018257600080fd5b6200018d836200013b565b602084810151919350906001600160401b0380821115620001ad57600080fd5b818601915086601f830112620001c257600080fd5b815181811115620001d757620001d762000158565b8060051b604051601f19603f83011681018181108582111715620001ff57620001ff62000158565b6040529182528482019250838101850191898311156200021e57600080fd5b938501935b82851015620002475762000237856200013b565b8452938501939285019262000223565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200029057634e487b7160e01b600052601160045260246000fd5b5060010190565b608051613da3620003006000396000818161018d01528181611798015281816127380152818161279d01528181612807015281816128cc0152818161297901528181612a5d01528181612b6401528181612c1001528181612cdf0152612df10152613da36000f3fe6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "deployedBytecode": "0x6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "devdoc": { + "author": "Ilya Lyalin", + "kind": "dev", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IAlgebraPoolActions#swap call" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the PancakeV3Pool#swap call" + } + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "route": "Route to process", + "to": "Where to transfer output tokens", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IUniswapV3PoolActions#swap call" + } + } + }, + "title": "A route processor for the Sushi Aggregator", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IAlgebraPool#swap." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via PancakeV3Pool#swap." + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "notice": "Processes the route generated off-chain. Has a lock" + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value of input tokens to and then processes the route" + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "processes the route and sends amount of output token to " + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value to and then processes the route" + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 1060, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "priviledgedUsers", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 1062, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "lastCalledPool", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 1065, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "unlocked", + "offset": 20, + "slot": "2", + "type": "t_uint8" + }, + { + "astId": 1068, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "paused", + "offset": 21, + "slot": "2", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/celo/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json b/protocols/route-processor/deployments/celo/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json new file mode 100644 index 0000000000..01826e7b93 --- /dev/null +++ b/protocols/route-processor/deployments/celo/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json @@ -0,0 +1,80 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" + }, + "contracts/InputStream.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" + }, + "contracts/RouteProcessor5.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" + }, + "contracts/Utils.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "interfaces/IBentoBoxMinimal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" + }, + "interfaces/ICurve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" + }, + "interfaces/IPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" + }, + "interfaces/ITridentCLPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/core/RouteProcessor5.json b/protocols/route-processor/deployments/core/RouteProcessor5.json new file mode 100644 index 0000000000..ea7519945d --- /dev/null +++ b/protocols/route-processor/deployments/core/RouteProcessor5.json @@ -0,0 +1,704 @@ +{ + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_bentoBox", + "type": "address" + }, + { + "internalType": "address[]", + "name": "priviledgedUserList", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "MinimalOutputBalanceViolation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Route", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "algebraSwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bentoBox", + "outputs": [ + { + "internalType": "contract IBentoBoxMinimal", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "pancakeV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "priviledgedUsers", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueInput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "priviledge", + "type": "bool" + } + ], + "name": "setPriviledge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "transferValueAndprocessRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0xf1e17e6428851c5c76e8b717c4914195830b42881eb88725e4ee181f3b6ce9ee", + "receipt": { + "to": null, + "from": "0x282607716D9B4fDD0B094d5864fac56313f5e665", + "contractAddress": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "transactionIndex": 13, + "gasUsed": "3487633", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000020000000000000000000000000000000000000001000000000000000000000000000000000000000000040000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000000000000000000000000000", + "blockHash": "0xef2447695b6edb10f6d35c242bf74671e5d767d94cbc607935f9fd84415da4c2", + "transactionHash": "0xf1e17e6428851c5c76e8b717c4914195830b42881eb88725e4ee181f3b6ce9ee", + "logs": [ + { + "transactionIndex": 13, + "blockNumber": 16313562, + "transactionHash": "0xf1e17e6428851c5c76e8b717c4914195830b42881eb88725e4ee181f3b6ce9ee", + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000282607716d9b4fdd0b094d5864fac56313f5e665" + ], + "data": "0x", + "logIndex": 31, + "blockHash": "0xef2447695b6edb10f6d35c242bf74671e5d767d94cbc607935f9fd84415da4c2" + } + ], + "blockNumber": 16313562, + "cumulativeGasUsed": "5169347", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000000", + [] + ], + "numDeployments": 1, + "solcInputHash": "e556d43a3caf4f1fb4f12d632d103b28", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bentoBox\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"priviledgedUserList\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"MinimalOutputBalanceViolation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"Route\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"algebraSwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"pancakeV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"priviledgedUsers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"priviledge\",\"type\":\"bool\"}],\"name\":\"setPriviledge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"transferValueAndprocessRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"Ilya Lyalin\",\"kind\":\"dev\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IAlgebraPoolActions#swap call\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the PancakeV3Pool#swap call\"}},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"route\":\"Route to process\",\"to\":\"Where to transfer output tokens\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IUniswapV3PoolActions#swap call\"}}},\"title\":\"A route processor for the Sushi Aggregator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\"},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Processes the route generated off-chain. Has a lock\"},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value of input tokens to and then processes the route\"},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"processes the route and sends amount of output token to \"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value to and then processes the route\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RouteProcessor5.sol\":\"RouteProcessor5\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\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 Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.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 function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\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\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\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 * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\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\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/InputStream.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\n/** @notice Simple read stream */\\nlibrary InputStream {\\n\\n /** @notice Creates stream from data\\n * @param data data\\n */\\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\\n assembly {\\n stream := mload(0x40)\\n mstore(0x40, add(stream, 64))\\n mstore(stream, data)\\n let length := mload(data)\\n mstore(add(stream, 32), add(data, length))\\n }\\n }\\n\\n /** @notice Checks if stream is not empty\\n * @param stream stream\\n */\\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\\n uint256 pos;\\n uint256 finish;\\n assembly {\\n pos := mload(stream)\\n finish := mload(add(stream, 32))\\n }\\n return pos < finish;\\n }\\n\\n /** @notice Reads uint8 from the stream\\n * @param stream stream\\n */\\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 1)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint16 from the stream\\n * @param stream stream\\n */\\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 2)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint24 from the stream\\n * @param stream stream\\n */\\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 3)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint32 from the stream\\n * @param stream stream\\n */\\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 4)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint256 from the stream\\n * @param stream stream\\n */\\n function readUint(uint256 stream) internal pure returns (uint256 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes32 from the stream\\n * @param stream stream\\n */\\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads address from the stream\\n * @param stream stream\\n */\\n function readAddress(uint256 stream) internal pure returns (address res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 20)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes from the stream\\n * @param stream stream\\n */\\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\\n assembly {\\n let pos := mload(stream)\\n res := add(pos, 32)\\n let length := mload(res)\\n mstore(stream, add(res, length))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x24e24bd0e49cbddacbf3b26bcd4bdffac63d11f3259bc05bc93c0835e8ff5300\",\"license\":\"UNLICENSED\"},\"contracts/RouteProcessor5.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '../interfaces/IUniswapV2Pair.sol';\\nimport '../interfaces/IUniswapV3Pool.sol';\\nimport '../interfaces/ITridentCLPool.sol';\\nimport '../interfaces/IBentoBoxMinimal.sol';\\nimport '../interfaces/IPool.sol';\\nimport '../interfaces/IWETH.sol';\\nimport '../interfaces/ICurve.sol';\\nimport './InputStream.sol';\\nimport './Utils.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\\n\\nuint8 constant LOCKED = 2;\\nuint8 constant NOT_LOCKED = 1;\\nuint8 constant PAUSED = 2;\\nuint8 constant NOT_PAUSED = 1;\\n\\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\nuint160 constant MIN_SQRT_RATIO = 4295128739;\\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n/// @title A route processor for the Sushi Aggregator\\n/// @author Ilya Lyalin\\ncontract RouteProcessor5 is Ownable {\\n using SafeERC20 for IERC20;\\n using Utils for IERC20;\\n using Utils for address;\\n using SafeERC20 for IERC20Permit;\\n using InputStream for uint256;\\n\\n event Route(\\n address indexed from, \\n address to, \\n address indexed tokenIn, \\n address indexed tokenOut, \\n uint256 amountIn, \\n uint256 amountOutMin,\\n uint256 amountOut\\n );\\n\\n error MinimalOutputBalanceViolation(uint256 amountOut);\\n\\n IBentoBoxMinimal public immutable bentoBox;\\n mapping (address => bool) public priviledgedUsers;\\n address private lastCalledPool;\\n\\n uint8 private unlocked = NOT_LOCKED;\\n uint8 private paused = NOT_PAUSED;\\n modifier lock() {\\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\\n unlocked = LOCKED;\\n _;\\n unlocked = NOT_LOCKED;\\n }\\n\\n modifier onlyOwnerOrPriviledgedUser() {\\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \\\"RP: caller is not the owner or a privileged user\\\");\\n _;\\n }\\n\\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\\n bentoBox = IBentoBoxMinimal(_bentoBox);\\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n\\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\\n priviledgedUsers[priviledgedUserList[i]] = true;\\n }\\n }\\n\\n function setPriviledge(address user, bool priviledge) external onlyOwner {\\n priviledgedUsers[user] = priviledge;\\n }\\n\\n function pause() external onlyOwnerOrPriviledgedUser {\\n paused = PAUSED;\\n }\\n\\n function resume() external onlyOwnerOrPriviledgedUser {\\n paused = NOT_PAUSED;\\n }\\n\\n /// @notice For native unwrapping\\n receive() external payable {}\\n\\n /// @notice Processes the route generated off-chain. Has a lock\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @param to Where to transfer output tokens\\n /// @param route Route to process\\n /// @return amountOut Actual amount of the output token\\n function processRoute(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function transferValueAndprocessRoute(\\n address transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n transferValueTo.transferNative(amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value of input tokens to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueInput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n \\n /// @notice processes the route and sends amount of output token to \\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueOutput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\\n }\\n\\n /// @notice Processes the route generated off-chain\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteInternal(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) private returns (uint256 amountOut) {\\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\\n\\n uint256 realAmountIn = amountIn;\\n {\\n uint256 step = 0;\\n uint256 stream = InputStream.createStream(route);\\n while (stream.isNotEmpty()) {\\n uint8 commandCode = stream.readUint8();\\n if (commandCode == 1) {\\n uint256 usedAmount = processMyERC20(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 2) processUserERC20(stream, amountIn);\\n else if (commandCode == 3) {\\n uint256 usedAmount = processNative(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 4) processOnePool(stream);\\n else if (commandCode == 5) processInsideBento(stream);\\n else if (commandCode == 6) applyPermit(tokenIn, stream);\\n else revert('RouteProcessor: Unknown command code');\\n ++step;\\n }\\n }\\n\\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\\n if (tokenIn != Utils.NATIVE_ADDRESS)\\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\\n \\n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\\n\\n amountOut = balanceOutFinal - balanceOutInitial;\\n\\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\\n }\\n\\n /// @notice Applies ERC-2612 permit\\n /// @param tokenIn permitted token\\n /// @param stream Streamed program\\n function applyPermit(address tokenIn, uint256 stream) private {\\n uint256 value = stream.readUint();\\n uint256 deadline = stream.readUint();\\n uint8 v = stream.readUint8();\\n bytes32 r = stream.readBytes32();\\n bytes32 s = stream.readBytes32();\\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\\n }\\n }\\n\\n /// @notice Processes native coin: call swap for all pools that swap from native coin\\n /// @param stream Streamed program\\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\\n amountTotal = address(this).balance;\\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token from this contract balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\\n address token = stream.readAddress();\\n amountTotal = IERC20(token).balanceOf(address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n \\n /// @notice Processes ERC20 token from msg.sender balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n /// @param amountTotal Amount of tokens to take from msg.sender\\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\\n address token = stream.readAddress();\\n distributeAndSwap(stream, msg.sender, token, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token for cases when the token has only one output pool\\n /// @notice In this case liquidity is already at pool balance. This is an optimization\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processOnePool(uint256 stream) private {\\n address token = stream.readAddress();\\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\\n }\\n\\n /// @notice Processes Bento tokens \\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processInsideBento(uint256 stream) private {\\n address token = stream.readAddress();\\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n\\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountTotal Total amount of tokenIn for swaps \\n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\\n uint8 num = stream.readUint8();\\n unchecked {\\n for (uint256 i = 0; i < num; ++i) {\\n uint16 share = stream.readUint16();\\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\\n amountTotal -= amount;\\n swap(stream, from, tokenIn, amount);\\n }\\n }\\n }\\n\\n /// @notice Makes swap\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 poolType = stream.readUint8();\\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\\n else revert('RouteProcessor: Unknown pool type');\\n }\\n\\n /// @notice Wraps/unwraps native token\\n /// @param stream [direction & fake, recipient, wrapToken?]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 directionAndFake = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (directionAndFake & 1 == 1) { // wrap native\\n address wrapToken = stream.readAddress();\\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\\n } else { // unwrap native\\n if (directionAndFake & 2 == 0) {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IWETH(tokenIn).withdraw(amountIn);\\n }\\n to.transferNative(amountIn);\\n }\\n }\\n\\n /// @notice Bridge/unbridge tokens to/from Bento\\n /// @param stream [direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (direction > 0) { // outside to Bento\\n // deposit to arbitrary recipient is possible only from address(bentoBox)\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\\n else {\\n // tokens already are at address(bentoBox)\\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\\n bentoBox.strategyData(tokenIn).balance -\\n bentoBox.totals(tokenIn).elastic;\\n }\\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\\n } else { // Bento to outside\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\\n }\\n }\\n\\n /// @notice UniswapV2 pool swap\\n /// @param stream [pool, direction, recipient, fee]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\\n\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\\n\\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\\n\\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\\n }\\n\\n /// @notice Trident pool swap\\n /// @param stream [pool, swapData]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bytes memory swapData = stream.readBytes();\\n\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, pool, amountIn);\\n }\\n \\n IPool(pool).swap(swapData);\\n }\\n\\n /// @notice UniswapV3 pool swap\\n /// @param stream [pool, direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bool zeroForOne = stream.readUint8() > 0;\\n address recipient = stream.readAddress();\\n\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\\n\\n lastCalledPool = pool;\\n IUniswapV3Pool(pool).swap(\\n recipient,\\n zeroForOne,\\n int256(amountIn),\\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\\n abi.encode(tokenIn)\\n );\\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) public {\\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\\n \\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n (address tokenIn) = abi.decode(data, (address));\\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\\n function algebraSwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\\n function pancakeV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 poolType = stream.readUint8();\\n int128 fromIndex = int8(stream.readUint8());\\n int128 toIndex = int8(stream.readUint8());\\n address to = stream.readAddress();\\n address tokenOut = stream.readAddress();\\n\\n uint256 amountOut;\\n if (tokenIn == Utils.NATIVE_ADDRESS) {\\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\\n } else {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IERC20(tokenIn).approveSafe(pool, amountIn);\\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n else {\\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\\n amountOut = balanceAfter - balanceBefore;\\n }\\n }\\n\\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\\n }\\n}\\n\",\"keccak256\":\"0xcd53a7f473f1847d44c42777a194203cbff02b8c761cb2935402401f57c918a2\",\"license\":\"UNLICENSED\"},\"contracts/Utils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\n\\nlibrary Utils {\\n using SafeERC20 for IERC20;\\n\\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n /**\\n * @dev returns user's balance of token (or native)\\n */\\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\\n if (token == NATIVE_ADDRESS) return address(user).balance;\\n else return IERC20(token).balanceOf(user);\\n }\\n\\n /**\\n * @dev transfers native with correct revert bubble up\\n */\\n function transferNative(address to, uint256 amount) internal {\\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\\n if (!success) {\\n assembly {\\n revert(add(32, returnBytes), mload(returnBytes))\\n }\\n }\\n }\\n\\n /**\\n * @dev transfers ERC20 or native\\n */\\n function transferAny(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\\n else IERC20(token).safeTransfer(to, amount);\\n }\\n\\n /**\\n * @dev transfers from ERC20 or transfers native\\n */\\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n (bool success, bytes memory data) = address(token).call(\\n abi.encodeWithSelector(token.approve.selector, spender, amount)\\n );\\n return success && (data.length == 0 || abi.decode(data, (bool)));\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \\n * current allowance are not zero simultaniously (USDT for example). \\n * In second case it tries to set allowance to 0, and then back to amount.\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n return approveStable(token, spender, amount) \\n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\\n }\\n}\\n\",\"keccak256\":\"0x8c8439edc00b403abd3f34be75a06b1fe71152644ae9f19488af596bbc534ffe\",\"license\":\"UNLICENSED\"},\"interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\nstruct StrategyData {\\n uint64 strategyStartDate;\\n uint64 targetPercentage;\\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n function strategyData(address token) external view returns (StrategyData memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0x0c12eba7a5b9d22d37ab8883fe22d6a312a90682809dbd11c43f8e6ceaff73bf\",\"license\":\"UNLICENSED\"},\"interfaces/ICurve.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\ninterface ICurve {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\\n}\\n\\ninterface ICurveLegacy {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\\n}\\n\\n\",\"keccak256\":\"0x3d4940b3583e06dde20f12e92d2f6ac573b3f64bdaa1e8f480656a3763852518\",\"license\":\"UNLICENSED\"},\"interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/ITridentCLPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface ITridentCLPool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bool unwrapBento,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x572376b80c86a94692b0e27e6e63790b763295e32ba1f956c1d331fc1296de8d\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IUniswapV2Pair.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Pair {\\n event Approval(address indexed owner, address indexed spender, uint value);\\n event Transfer(address indexed from, address indexed to, uint value);\\n\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function allowance(address owner, address spender) external view returns (uint);\\n\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address to, uint value) external returns (bool);\\n function transferFrom(address from, address to, uint value) external returns (bool);\\n\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n function nonces(address owner) external view returns (uint);\\n\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n event Mint(address indexed sender, uint amount0, uint amount1);\\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\\n event Swap(\\n address indexed sender,\\n uint amount0In,\\n uint amount1In,\\n uint amount0Out,\\n uint amount1Out,\\n address indexed to\\n );\\n event Sync(uint112 reserve0, uint112 reserve1);\\n\\n function MINIMUM_LIQUIDITY() external pure returns (uint);\\n function factory() external view returns (address);\\n function token0() external view returns (address);\\n function token1() external view returns (address);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\\n function price0CumulativeLast() external view returns (uint);\\n function price1CumulativeLast() external view returns (uint);\\n function kLast() external view returns (uint);\\n\\n function mint(address to) external returns (uint liquidity);\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function skim(address to) external;\\n function sync() external;\\n\\n function initialize(address, address) external;\\n}\",\"keccak256\":\"0x08f9a63b34855eec941be8d36a04424f1a1725a2c030373fcef3afeb480ca385\",\"license\":\"GPL-3.0\"},\"interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IUniswapV3Pool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x2a4d7c6120e613f0e95d4dc8c650efb9b59e3c25c64e3e5c0a379281500f0a79\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IWETH.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0xae8529ae159f784b90fdcd0629bd03bf7b68accc81edccac53357ad08406a378\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}", + "bytecode": "0x60a06040526002805461ffff60a01b191661010160a01b1790553480156200002657600080fd5b50604051620040a3380380620040a383398101604081905262000049916200016e565b6200005433620000eb565b6001600160a01b038216608052600280546001600160a01b031916600117905560005b8151811015620000e25760018060008484815181106200009b576200009b62000257565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000d9816200026d565b91505062000077565b50505062000297565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200015357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200018257600080fd5b6200018d836200013b565b602084810151919350906001600160401b0380821115620001ad57600080fd5b818601915086601f830112620001c257600080fd5b815181811115620001d757620001d762000158565b8060051b604051601f19603f83011681018181108582111715620001ff57620001ff62000158565b6040529182528482019250838101850191898311156200021e57600080fd5b938501935b82851015620002475762000237856200013b565b8452938501939285019262000223565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200029057634e487b7160e01b600052601160045260246000fd5b5060010190565b608051613da3620003006000396000818161018d01528181611798015281816127380152818161279d01528181612807015281816128cc0152818161297901528181612a5d01528181612b6401528181612c1001528181612cdf0152612df10152613da36000f3fe6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "deployedBytecode": "0x6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "devdoc": { + "author": "Ilya Lyalin", + "kind": "dev", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IAlgebraPoolActions#swap call" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the PancakeV3Pool#swap call" + } + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "route": "Route to process", + "to": "Where to transfer output tokens", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IUniswapV3PoolActions#swap call" + } + } + }, + "title": "A route processor for the Sushi Aggregator", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IAlgebraPool#swap." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via PancakeV3Pool#swap." + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "notice": "Processes the route generated off-chain. Has a lock" + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value of input tokens to and then processes the route" + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "processes the route and sends amount of output token to " + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value to and then processes the route" + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 1060, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "priviledgedUsers", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 1062, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "lastCalledPool", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 1065, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "unlocked", + "offset": 20, + "slot": "2", + "type": "t_uint8" + }, + { + "astId": 1068, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "paused", + "offset": 21, + "slot": "2", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/core/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json b/protocols/route-processor/deployments/core/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json new file mode 100644 index 0000000000..01826e7b93 --- /dev/null +++ b/protocols/route-processor/deployments/core/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json @@ -0,0 +1,80 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" + }, + "contracts/InputStream.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" + }, + "contracts/RouteProcessor5.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" + }, + "contracts/Utils.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "interfaces/IBentoBoxMinimal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" + }, + "interfaces/ICurve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" + }, + "interfaces/IPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" + }, + "interfaces/ITridentCLPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/ethereum/RouteProcessor5.json b/protocols/route-processor/deployments/ethereum/RouteProcessor5.json new file mode 100644 index 0000000000..dc2a073c8a --- /dev/null +++ b/protocols/route-processor/deployments/ethereum/RouteProcessor5.json @@ -0,0 +1,704 @@ +{ + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_bentoBox", + "type": "address" + }, + { + "internalType": "address[]", + "name": "priviledgedUserList", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "MinimalOutputBalanceViolation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Route", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "algebraSwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bentoBox", + "outputs": [ + { + "internalType": "contract IBentoBoxMinimal", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "pancakeV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "priviledgedUsers", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueInput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "priviledge", + "type": "bool" + } + ], + "name": "setPriviledge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "transferValueAndprocessRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x4ecc0deab15abf7230395db612045f6b716de4713f8b943ce1e4dc2db0758943", + "receipt": { + "to": null, + "from": "0x282607716D9B4fDD0B094d5864fac56313f5e665", + "contractAddress": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "transactionIndex": 49, + "gasUsed": "3489875", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000020000000000000000000000000000000000000001000000000000000000000000000000000000000000040000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000000000000000000000000000", + "blockHash": "0xcdc1b9c4571e254701f8c2105d707dde46a10b76a9d38f3f121de94b68693291", + "transactionHash": "0x4ecc0deab15abf7230395db612045f6b716de4713f8b943ce1e4dc2db0758943", + "logs": [ + { + "transactionIndex": 49, + "blockNumber": 20411044, + "transactionHash": "0x4ecc0deab15abf7230395db612045f6b716de4713f8b943ce1e4dc2db0758943", + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000282607716d9b4fdd0b094d5864fac56313f5e665" + ], + "data": "0x", + "logIndex": 83, + "blockHash": "0xcdc1b9c4571e254701f8c2105d707dde46a10b76a9d38f3f121de94b68693291" + } + ], + "blockNumber": 20411044, + "cumulativeGasUsed": "6849714", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000000", + [] + ], + "numDeployments": 1, + "solcInputHash": "e556d43a3caf4f1fb4f12d632d103b28", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bentoBox\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"priviledgedUserList\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"MinimalOutputBalanceViolation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"Route\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"algebraSwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"pancakeV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"priviledgedUsers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"priviledge\",\"type\":\"bool\"}],\"name\":\"setPriviledge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"transferValueAndprocessRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"Ilya Lyalin\",\"kind\":\"dev\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IAlgebraPoolActions#swap call\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the PancakeV3Pool#swap call\"}},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"route\":\"Route to process\",\"to\":\"Where to transfer output tokens\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IUniswapV3PoolActions#swap call\"}}},\"title\":\"A route processor for the Sushi Aggregator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\"},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Processes the route generated off-chain. Has a lock\"},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value of input tokens to and then processes the route\"},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"processes the route and sends amount of output token to \"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value to and then processes the route\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RouteProcessor5.sol\":\"RouteProcessor5\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\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 Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.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 function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\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\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\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 * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\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\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/InputStream.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\n/** @notice Simple read stream */\\nlibrary InputStream {\\n\\n /** @notice Creates stream from data\\n * @param data data\\n */\\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\\n assembly {\\n stream := mload(0x40)\\n mstore(0x40, add(stream, 64))\\n mstore(stream, data)\\n let length := mload(data)\\n mstore(add(stream, 32), add(data, length))\\n }\\n }\\n\\n /** @notice Checks if stream is not empty\\n * @param stream stream\\n */\\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\\n uint256 pos;\\n uint256 finish;\\n assembly {\\n pos := mload(stream)\\n finish := mload(add(stream, 32))\\n }\\n return pos < finish;\\n }\\n\\n /** @notice Reads uint8 from the stream\\n * @param stream stream\\n */\\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 1)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint16 from the stream\\n * @param stream stream\\n */\\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 2)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint24 from the stream\\n * @param stream stream\\n */\\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 3)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint32 from the stream\\n * @param stream stream\\n */\\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 4)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint256 from the stream\\n * @param stream stream\\n */\\n function readUint(uint256 stream) internal pure returns (uint256 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes32 from the stream\\n * @param stream stream\\n */\\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads address from the stream\\n * @param stream stream\\n */\\n function readAddress(uint256 stream) internal pure returns (address res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 20)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes from the stream\\n * @param stream stream\\n */\\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\\n assembly {\\n let pos := mload(stream)\\n res := add(pos, 32)\\n let length := mload(res)\\n mstore(stream, add(res, length))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x24e24bd0e49cbddacbf3b26bcd4bdffac63d11f3259bc05bc93c0835e8ff5300\",\"license\":\"UNLICENSED\"},\"contracts/RouteProcessor5.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '../interfaces/IUniswapV2Pair.sol';\\nimport '../interfaces/IUniswapV3Pool.sol';\\nimport '../interfaces/ITridentCLPool.sol';\\nimport '../interfaces/IBentoBoxMinimal.sol';\\nimport '../interfaces/IPool.sol';\\nimport '../interfaces/IWETH.sol';\\nimport '../interfaces/ICurve.sol';\\nimport './InputStream.sol';\\nimport './Utils.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\\n\\nuint8 constant LOCKED = 2;\\nuint8 constant NOT_LOCKED = 1;\\nuint8 constant PAUSED = 2;\\nuint8 constant NOT_PAUSED = 1;\\n\\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\nuint160 constant MIN_SQRT_RATIO = 4295128739;\\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n/// @title A route processor for the Sushi Aggregator\\n/// @author Ilya Lyalin\\ncontract RouteProcessor5 is Ownable {\\n using SafeERC20 for IERC20;\\n using Utils for IERC20;\\n using Utils for address;\\n using SafeERC20 for IERC20Permit;\\n using InputStream for uint256;\\n\\n event Route(\\n address indexed from, \\n address to, \\n address indexed tokenIn, \\n address indexed tokenOut, \\n uint256 amountIn, \\n uint256 amountOutMin,\\n uint256 amountOut\\n );\\n\\n error MinimalOutputBalanceViolation(uint256 amountOut);\\n\\n IBentoBoxMinimal public immutable bentoBox;\\n mapping (address => bool) public priviledgedUsers;\\n address private lastCalledPool;\\n\\n uint8 private unlocked = NOT_LOCKED;\\n uint8 private paused = NOT_PAUSED;\\n modifier lock() {\\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\\n unlocked = LOCKED;\\n _;\\n unlocked = NOT_LOCKED;\\n }\\n\\n modifier onlyOwnerOrPriviledgedUser() {\\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \\\"RP: caller is not the owner or a privileged user\\\");\\n _;\\n }\\n\\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\\n bentoBox = IBentoBoxMinimal(_bentoBox);\\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n\\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\\n priviledgedUsers[priviledgedUserList[i]] = true;\\n }\\n }\\n\\n function setPriviledge(address user, bool priviledge) external onlyOwner {\\n priviledgedUsers[user] = priviledge;\\n }\\n\\n function pause() external onlyOwnerOrPriviledgedUser {\\n paused = PAUSED;\\n }\\n\\n function resume() external onlyOwnerOrPriviledgedUser {\\n paused = NOT_PAUSED;\\n }\\n\\n /// @notice For native unwrapping\\n receive() external payable {}\\n\\n /// @notice Processes the route generated off-chain. Has a lock\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @param to Where to transfer output tokens\\n /// @param route Route to process\\n /// @return amountOut Actual amount of the output token\\n function processRoute(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function transferValueAndprocessRoute(\\n address transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n transferValueTo.transferNative(amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value of input tokens to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueInput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n \\n /// @notice processes the route and sends amount of output token to \\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueOutput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\\n }\\n\\n /// @notice Processes the route generated off-chain\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteInternal(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) private returns (uint256 amountOut) {\\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\\n\\n uint256 realAmountIn = amountIn;\\n {\\n uint256 step = 0;\\n uint256 stream = InputStream.createStream(route);\\n while (stream.isNotEmpty()) {\\n uint8 commandCode = stream.readUint8();\\n if (commandCode == 1) {\\n uint256 usedAmount = processMyERC20(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 2) processUserERC20(stream, amountIn);\\n else if (commandCode == 3) {\\n uint256 usedAmount = processNative(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 4) processOnePool(stream);\\n else if (commandCode == 5) processInsideBento(stream);\\n else if (commandCode == 6) applyPermit(tokenIn, stream);\\n else revert('RouteProcessor: Unknown command code');\\n ++step;\\n }\\n }\\n\\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\\n if (tokenIn != Utils.NATIVE_ADDRESS)\\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\\n \\n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\\n\\n amountOut = balanceOutFinal - balanceOutInitial;\\n\\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\\n }\\n\\n /// @notice Applies ERC-2612 permit\\n /// @param tokenIn permitted token\\n /// @param stream Streamed program\\n function applyPermit(address tokenIn, uint256 stream) private {\\n uint256 value = stream.readUint();\\n uint256 deadline = stream.readUint();\\n uint8 v = stream.readUint8();\\n bytes32 r = stream.readBytes32();\\n bytes32 s = stream.readBytes32();\\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\\n }\\n }\\n\\n /// @notice Processes native coin: call swap for all pools that swap from native coin\\n /// @param stream Streamed program\\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\\n amountTotal = address(this).balance;\\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token from this contract balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\\n address token = stream.readAddress();\\n amountTotal = IERC20(token).balanceOf(address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n \\n /// @notice Processes ERC20 token from msg.sender balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n /// @param amountTotal Amount of tokens to take from msg.sender\\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\\n address token = stream.readAddress();\\n distributeAndSwap(stream, msg.sender, token, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token for cases when the token has only one output pool\\n /// @notice In this case liquidity is already at pool balance. This is an optimization\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processOnePool(uint256 stream) private {\\n address token = stream.readAddress();\\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\\n }\\n\\n /// @notice Processes Bento tokens \\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processInsideBento(uint256 stream) private {\\n address token = stream.readAddress();\\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n\\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountTotal Total amount of tokenIn for swaps \\n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\\n uint8 num = stream.readUint8();\\n unchecked {\\n for (uint256 i = 0; i < num; ++i) {\\n uint16 share = stream.readUint16();\\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\\n amountTotal -= amount;\\n swap(stream, from, tokenIn, amount);\\n }\\n }\\n }\\n\\n /// @notice Makes swap\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 poolType = stream.readUint8();\\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\\n else revert('RouteProcessor: Unknown pool type');\\n }\\n\\n /// @notice Wraps/unwraps native token\\n /// @param stream [direction & fake, recipient, wrapToken?]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 directionAndFake = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (directionAndFake & 1 == 1) { // wrap native\\n address wrapToken = stream.readAddress();\\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\\n } else { // unwrap native\\n if (directionAndFake & 2 == 0) {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IWETH(tokenIn).withdraw(amountIn);\\n }\\n to.transferNative(amountIn);\\n }\\n }\\n\\n /// @notice Bridge/unbridge tokens to/from Bento\\n /// @param stream [direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (direction > 0) { // outside to Bento\\n // deposit to arbitrary recipient is possible only from address(bentoBox)\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\\n else {\\n // tokens already are at address(bentoBox)\\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\\n bentoBox.strategyData(tokenIn).balance -\\n bentoBox.totals(tokenIn).elastic;\\n }\\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\\n } else { // Bento to outside\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\\n }\\n }\\n\\n /// @notice UniswapV2 pool swap\\n /// @param stream [pool, direction, recipient, fee]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\\n\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\\n\\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\\n\\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\\n }\\n\\n /// @notice Trident pool swap\\n /// @param stream [pool, swapData]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bytes memory swapData = stream.readBytes();\\n\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, pool, amountIn);\\n }\\n \\n IPool(pool).swap(swapData);\\n }\\n\\n /// @notice UniswapV3 pool swap\\n /// @param stream [pool, direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bool zeroForOne = stream.readUint8() > 0;\\n address recipient = stream.readAddress();\\n\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\\n\\n lastCalledPool = pool;\\n IUniswapV3Pool(pool).swap(\\n recipient,\\n zeroForOne,\\n int256(amountIn),\\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\\n abi.encode(tokenIn)\\n );\\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) public {\\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\\n \\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n (address tokenIn) = abi.decode(data, (address));\\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\\n function algebraSwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\\n function pancakeV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 poolType = stream.readUint8();\\n int128 fromIndex = int8(stream.readUint8());\\n int128 toIndex = int8(stream.readUint8());\\n address to = stream.readAddress();\\n address tokenOut = stream.readAddress();\\n\\n uint256 amountOut;\\n if (tokenIn == Utils.NATIVE_ADDRESS) {\\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\\n } else {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IERC20(tokenIn).approveSafe(pool, amountIn);\\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n else {\\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\\n amountOut = balanceAfter - balanceBefore;\\n }\\n }\\n\\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\\n }\\n}\\n\",\"keccak256\":\"0xcd53a7f473f1847d44c42777a194203cbff02b8c761cb2935402401f57c918a2\",\"license\":\"UNLICENSED\"},\"contracts/Utils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\n\\nlibrary Utils {\\n using SafeERC20 for IERC20;\\n\\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n /**\\n * @dev returns user's balance of token (or native)\\n */\\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\\n if (token == NATIVE_ADDRESS) return address(user).balance;\\n else return IERC20(token).balanceOf(user);\\n }\\n\\n /**\\n * @dev transfers native with correct revert bubble up\\n */\\n function transferNative(address to, uint256 amount) internal {\\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\\n if (!success) {\\n assembly {\\n revert(add(32, returnBytes), mload(returnBytes))\\n }\\n }\\n }\\n\\n /**\\n * @dev transfers ERC20 or native\\n */\\n function transferAny(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\\n else IERC20(token).safeTransfer(to, amount);\\n }\\n\\n /**\\n * @dev transfers from ERC20 or transfers native\\n */\\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n (bool success, bytes memory data) = address(token).call(\\n abi.encodeWithSelector(token.approve.selector, spender, amount)\\n );\\n return success && (data.length == 0 || abi.decode(data, (bool)));\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \\n * current allowance are not zero simultaniously (USDT for example). \\n * In second case it tries to set allowance to 0, and then back to amount.\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n return approveStable(token, spender, amount) \\n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\\n }\\n}\\n\",\"keccak256\":\"0x8c8439edc00b403abd3f34be75a06b1fe71152644ae9f19488af596bbc534ffe\",\"license\":\"UNLICENSED\"},\"interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\nstruct StrategyData {\\n uint64 strategyStartDate;\\n uint64 targetPercentage;\\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n function strategyData(address token) external view returns (StrategyData memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0x0c12eba7a5b9d22d37ab8883fe22d6a312a90682809dbd11c43f8e6ceaff73bf\",\"license\":\"UNLICENSED\"},\"interfaces/ICurve.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\ninterface ICurve {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\\n}\\n\\ninterface ICurveLegacy {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\\n}\\n\\n\",\"keccak256\":\"0x3d4940b3583e06dde20f12e92d2f6ac573b3f64bdaa1e8f480656a3763852518\",\"license\":\"UNLICENSED\"},\"interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/ITridentCLPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface ITridentCLPool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bool unwrapBento,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x572376b80c86a94692b0e27e6e63790b763295e32ba1f956c1d331fc1296de8d\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IUniswapV2Pair.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Pair {\\n event Approval(address indexed owner, address indexed spender, uint value);\\n event Transfer(address indexed from, address indexed to, uint value);\\n\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function allowance(address owner, address spender) external view returns (uint);\\n\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address to, uint value) external returns (bool);\\n function transferFrom(address from, address to, uint value) external returns (bool);\\n\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n function nonces(address owner) external view returns (uint);\\n\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n event Mint(address indexed sender, uint amount0, uint amount1);\\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\\n event Swap(\\n address indexed sender,\\n uint amount0In,\\n uint amount1In,\\n uint amount0Out,\\n uint amount1Out,\\n address indexed to\\n );\\n event Sync(uint112 reserve0, uint112 reserve1);\\n\\n function MINIMUM_LIQUIDITY() external pure returns (uint);\\n function factory() external view returns (address);\\n function token0() external view returns (address);\\n function token1() external view returns (address);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\\n function price0CumulativeLast() external view returns (uint);\\n function price1CumulativeLast() external view returns (uint);\\n function kLast() external view returns (uint);\\n\\n function mint(address to) external returns (uint liquidity);\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function skim(address to) external;\\n function sync() external;\\n\\n function initialize(address, address) external;\\n}\",\"keccak256\":\"0x08f9a63b34855eec941be8d36a04424f1a1725a2c030373fcef3afeb480ca385\",\"license\":\"GPL-3.0\"},\"interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IUniswapV3Pool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x2a4d7c6120e613f0e95d4dc8c650efb9b59e3c25c64e3e5c0a379281500f0a79\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IWETH.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0xae8529ae159f784b90fdcd0629bd03bf7b68accc81edccac53357ad08406a378\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}", + "bytecode": "0x60a06040526002805461ffff60a01b191661010160a01b1790553480156200002657600080fd5b50604051620040a3380380620040a383398101604081905262000049916200016e565b6200005433620000eb565b6001600160a01b038216608052600280546001600160a01b031916600117905560005b8151811015620000e25760018060008484815181106200009b576200009b62000257565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000d9816200026d565b91505062000077565b50505062000297565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200015357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200018257600080fd5b6200018d836200013b565b602084810151919350906001600160401b0380821115620001ad57600080fd5b818601915086601f830112620001c257600080fd5b815181811115620001d757620001d762000158565b8060051b604051601f19603f83011681018181108582111715620001ff57620001ff62000158565b6040529182528482019250838101850191898311156200021e57600080fd5b938501935b82851015620002475762000237856200013b565b8452938501939285019262000223565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200029057634e487b7160e01b600052601160045260246000fd5b5060010190565b608051613da3620003006000396000818161018d01528181611798015281816127380152818161279d01528181612807015281816128cc0152818161297901528181612a5d01528181612b6401528181612c1001528181612cdf0152612df10152613da36000f3fe6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "deployedBytecode": "0x6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "devdoc": { + "author": "Ilya Lyalin", + "kind": "dev", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IAlgebraPoolActions#swap call" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the PancakeV3Pool#swap call" + } + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "route": "Route to process", + "to": "Where to transfer output tokens", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IUniswapV3PoolActions#swap call" + } + } + }, + "title": "A route processor for the Sushi Aggregator", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IAlgebraPool#swap." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via PancakeV3Pool#swap." + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "notice": "Processes the route generated off-chain. Has a lock" + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value of input tokens to and then processes the route" + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "processes the route and sends amount of output token to " + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value to and then processes the route" + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 1060, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "priviledgedUsers", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 1062, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "lastCalledPool", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 1065, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "unlocked", + "offset": 20, + "slot": "2", + "type": "t_uint8" + }, + { + "astId": 1068, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "paused", + "offset": 21, + "slot": "2", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/ethereum/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json b/protocols/route-processor/deployments/ethereum/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json new file mode 100644 index 0000000000..01826e7b93 --- /dev/null +++ b/protocols/route-processor/deployments/ethereum/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json @@ -0,0 +1,80 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" + }, + "contracts/InputStream.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" + }, + "contracts/RouteProcessor5.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" + }, + "contracts/Utils.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "interfaces/IBentoBoxMinimal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" + }, + "interfaces/ICurve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" + }, + "interfaces/IPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" + }, + "interfaces/ITridentCLPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/fantom/RouteProcessor5.json b/protocols/route-processor/deployments/fantom/RouteProcessor5.json new file mode 100644 index 0000000000..3d73a1e74f --- /dev/null +++ b/protocols/route-processor/deployments/fantom/RouteProcessor5.json @@ -0,0 +1,704 @@ +{ + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_bentoBox", + "type": "address" + }, + { + "internalType": "address[]", + "name": "priviledgedUserList", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "MinimalOutputBalanceViolation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Route", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "algebraSwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bentoBox", + "outputs": [ + { + "internalType": "contract IBentoBoxMinimal", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "pancakeV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "priviledgedUsers", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueInput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "priviledge", + "type": "bool" + } + ], + "name": "setPriviledge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "transferValueAndprocessRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x5ec686d294cd07e29aa00179e3ac65e0da30a34ee95ae6dbcd005859846a8c46", + "receipt": { + "to": null, + "from": "0x282607716D9B4fDD0B094d5864fac56313f5e665", + "contractAddress": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "transactionIndex": 0, + "gasUsed": "3488833", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000020000000000000000000000000000000000000001000000000000000000000000000000000000000000040000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000000000000000000000000000", + "blockHash": "0x000485b000000bbe06d5a26abd268948f162546f3f28deda4c842582582e5c32", + "transactionHash": "0x5ec686d294cd07e29aa00179e3ac65e0da30a34ee95ae6dbcd005859846a8c46", + "logs": [ + { + "transactionIndex": 0, + "blockNumber": 87093263, + "transactionHash": "0x5ec686d294cd07e29aa00179e3ac65e0da30a34ee95ae6dbcd005859846a8c46", + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000282607716d9b4fdd0b094d5864fac56313f5e665" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0x000485b000000bbe06d5a26abd268948f162546f3f28deda4c842582582e5c32" + } + ], + "blockNumber": 87093263, + "cumulativeGasUsed": "3488833", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000000", + [] + ], + "numDeployments": 1, + "solcInputHash": "e556d43a3caf4f1fb4f12d632d103b28", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bentoBox\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"priviledgedUserList\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"MinimalOutputBalanceViolation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"Route\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"algebraSwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"pancakeV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"priviledgedUsers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"priviledge\",\"type\":\"bool\"}],\"name\":\"setPriviledge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"transferValueAndprocessRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"Ilya Lyalin\",\"kind\":\"dev\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IAlgebraPoolActions#swap call\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the PancakeV3Pool#swap call\"}},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"route\":\"Route to process\",\"to\":\"Where to transfer output tokens\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IUniswapV3PoolActions#swap call\"}}},\"title\":\"A route processor for the Sushi Aggregator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\"},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Processes the route generated off-chain. Has a lock\"},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value of input tokens to and then processes the route\"},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"processes the route and sends amount of output token to \"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value to and then processes the route\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RouteProcessor5.sol\":\"RouteProcessor5\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\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 Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.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 function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\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\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\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 * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\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\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/InputStream.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\n/** @notice Simple read stream */\\nlibrary InputStream {\\n\\n /** @notice Creates stream from data\\n * @param data data\\n */\\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\\n assembly {\\n stream := mload(0x40)\\n mstore(0x40, add(stream, 64))\\n mstore(stream, data)\\n let length := mload(data)\\n mstore(add(stream, 32), add(data, length))\\n }\\n }\\n\\n /** @notice Checks if stream is not empty\\n * @param stream stream\\n */\\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\\n uint256 pos;\\n uint256 finish;\\n assembly {\\n pos := mload(stream)\\n finish := mload(add(stream, 32))\\n }\\n return pos < finish;\\n }\\n\\n /** @notice Reads uint8 from the stream\\n * @param stream stream\\n */\\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 1)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint16 from the stream\\n * @param stream stream\\n */\\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 2)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint24 from the stream\\n * @param stream stream\\n */\\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 3)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint32 from the stream\\n * @param stream stream\\n */\\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 4)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint256 from the stream\\n * @param stream stream\\n */\\n function readUint(uint256 stream) internal pure returns (uint256 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes32 from the stream\\n * @param stream stream\\n */\\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads address from the stream\\n * @param stream stream\\n */\\n function readAddress(uint256 stream) internal pure returns (address res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 20)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes from the stream\\n * @param stream stream\\n */\\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\\n assembly {\\n let pos := mload(stream)\\n res := add(pos, 32)\\n let length := mload(res)\\n mstore(stream, add(res, length))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x24e24bd0e49cbddacbf3b26bcd4bdffac63d11f3259bc05bc93c0835e8ff5300\",\"license\":\"UNLICENSED\"},\"contracts/RouteProcessor5.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '../interfaces/IUniswapV2Pair.sol';\\nimport '../interfaces/IUniswapV3Pool.sol';\\nimport '../interfaces/ITridentCLPool.sol';\\nimport '../interfaces/IBentoBoxMinimal.sol';\\nimport '../interfaces/IPool.sol';\\nimport '../interfaces/IWETH.sol';\\nimport '../interfaces/ICurve.sol';\\nimport './InputStream.sol';\\nimport './Utils.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\\n\\nuint8 constant LOCKED = 2;\\nuint8 constant NOT_LOCKED = 1;\\nuint8 constant PAUSED = 2;\\nuint8 constant NOT_PAUSED = 1;\\n\\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\nuint160 constant MIN_SQRT_RATIO = 4295128739;\\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n/// @title A route processor for the Sushi Aggregator\\n/// @author Ilya Lyalin\\ncontract RouteProcessor5 is Ownable {\\n using SafeERC20 for IERC20;\\n using Utils for IERC20;\\n using Utils for address;\\n using SafeERC20 for IERC20Permit;\\n using InputStream for uint256;\\n\\n event Route(\\n address indexed from, \\n address to, \\n address indexed tokenIn, \\n address indexed tokenOut, \\n uint256 amountIn, \\n uint256 amountOutMin,\\n uint256 amountOut\\n );\\n\\n error MinimalOutputBalanceViolation(uint256 amountOut);\\n\\n IBentoBoxMinimal public immutable bentoBox;\\n mapping (address => bool) public priviledgedUsers;\\n address private lastCalledPool;\\n\\n uint8 private unlocked = NOT_LOCKED;\\n uint8 private paused = NOT_PAUSED;\\n modifier lock() {\\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\\n unlocked = LOCKED;\\n _;\\n unlocked = NOT_LOCKED;\\n }\\n\\n modifier onlyOwnerOrPriviledgedUser() {\\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \\\"RP: caller is not the owner or a privileged user\\\");\\n _;\\n }\\n\\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\\n bentoBox = IBentoBoxMinimal(_bentoBox);\\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n\\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\\n priviledgedUsers[priviledgedUserList[i]] = true;\\n }\\n }\\n\\n function setPriviledge(address user, bool priviledge) external onlyOwner {\\n priviledgedUsers[user] = priviledge;\\n }\\n\\n function pause() external onlyOwnerOrPriviledgedUser {\\n paused = PAUSED;\\n }\\n\\n function resume() external onlyOwnerOrPriviledgedUser {\\n paused = NOT_PAUSED;\\n }\\n\\n /// @notice For native unwrapping\\n receive() external payable {}\\n\\n /// @notice Processes the route generated off-chain. Has a lock\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @param to Where to transfer output tokens\\n /// @param route Route to process\\n /// @return amountOut Actual amount of the output token\\n function processRoute(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function transferValueAndprocessRoute(\\n address transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n transferValueTo.transferNative(amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value of input tokens to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueInput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n \\n /// @notice processes the route and sends amount of output token to \\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueOutput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\\n }\\n\\n /// @notice Processes the route generated off-chain\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteInternal(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) private returns (uint256 amountOut) {\\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\\n\\n uint256 realAmountIn = amountIn;\\n {\\n uint256 step = 0;\\n uint256 stream = InputStream.createStream(route);\\n while (stream.isNotEmpty()) {\\n uint8 commandCode = stream.readUint8();\\n if (commandCode == 1) {\\n uint256 usedAmount = processMyERC20(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 2) processUserERC20(stream, amountIn);\\n else if (commandCode == 3) {\\n uint256 usedAmount = processNative(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 4) processOnePool(stream);\\n else if (commandCode == 5) processInsideBento(stream);\\n else if (commandCode == 6) applyPermit(tokenIn, stream);\\n else revert('RouteProcessor: Unknown command code');\\n ++step;\\n }\\n }\\n\\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\\n if (tokenIn != Utils.NATIVE_ADDRESS)\\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\\n \\n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\\n\\n amountOut = balanceOutFinal - balanceOutInitial;\\n\\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\\n }\\n\\n /// @notice Applies ERC-2612 permit\\n /// @param tokenIn permitted token\\n /// @param stream Streamed program\\n function applyPermit(address tokenIn, uint256 stream) private {\\n uint256 value = stream.readUint();\\n uint256 deadline = stream.readUint();\\n uint8 v = stream.readUint8();\\n bytes32 r = stream.readBytes32();\\n bytes32 s = stream.readBytes32();\\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\\n }\\n }\\n\\n /// @notice Processes native coin: call swap for all pools that swap from native coin\\n /// @param stream Streamed program\\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\\n amountTotal = address(this).balance;\\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token from this contract balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\\n address token = stream.readAddress();\\n amountTotal = IERC20(token).balanceOf(address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n \\n /// @notice Processes ERC20 token from msg.sender balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n /// @param amountTotal Amount of tokens to take from msg.sender\\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\\n address token = stream.readAddress();\\n distributeAndSwap(stream, msg.sender, token, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token for cases when the token has only one output pool\\n /// @notice In this case liquidity is already at pool balance. This is an optimization\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processOnePool(uint256 stream) private {\\n address token = stream.readAddress();\\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\\n }\\n\\n /// @notice Processes Bento tokens \\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processInsideBento(uint256 stream) private {\\n address token = stream.readAddress();\\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n\\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountTotal Total amount of tokenIn for swaps \\n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\\n uint8 num = stream.readUint8();\\n unchecked {\\n for (uint256 i = 0; i < num; ++i) {\\n uint16 share = stream.readUint16();\\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\\n amountTotal -= amount;\\n swap(stream, from, tokenIn, amount);\\n }\\n }\\n }\\n\\n /// @notice Makes swap\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 poolType = stream.readUint8();\\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\\n else revert('RouteProcessor: Unknown pool type');\\n }\\n\\n /// @notice Wraps/unwraps native token\\n /// @param stream [direction & fake, recipient, wrapToken?]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 directionAndFake = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (directionAndFake & 1 == 1) { // wrap native\\n address wrapToken = stream.readAddress();\\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\\n } else { // unwrap native\\n if (directionAndFake & 2 == 0) {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IWETH(tokenIn).withdraw(amountIn);\\n }\\n to.transferNative(amountIn);\\n }\\n }\\n\\n /// @notice Bridge/unbridge tokens to/from Bento\\n /// @param stream [direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (direction > 0) { // outside to Bento\\n // deposit to arbitrary recipient is possible only from address(bentoBox)\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\\n else {\\n // tokens already are at address(bentoBox)\\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\\n bentoBox.strategyData(tokenIn).balance -\\n bentoBox.totals(tokenIn).elastic;\\n }\\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\\n } else { // Bento to outside\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\\n }\\n }\\n\\n /// @notice UniswapV2 pool swap\\n /// @param stream [pool, direction, recipient, fee]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\\n\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\\n\\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\\n\\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\\n }\\n\\n /// @notice Trident pool swap\\n /// @param stream [pool, swapData]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bytes memory swapData = stream.readBytes();\\n\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, pool, amountIn);\\n }\\n \\n IPool(pool).swap(swapData);\\n }\\n\\n /// @notice UniswapV3 pool swap\\n /// @param stream [pool, direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bool zeroForOne = stream.readUint8() > 0;\\n address recipient = stream.readAddress();\\n\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\\n\\n lastCalledPool = pool;\\n IUniswapV3Pool(pool).swap(\\n recipient,\\n zeroForOne,\\n int256(amountIn),\\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\\n abi.encode(tokenIn)\\n );\\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) public {\\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\\n \\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n (address tokenIn) = abi.decode(data, (address));\\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\\n function algebraSwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\\n function pancakeV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 poolType = stream.readUint8();\\n int128 fromIndex = int8(stream.readUint8());\\n int128 toIndex = int8(stream.readUint8());\\n address to = stream.readAddress();\\n address tokenOut = stream.readAddress();\\n\\n uint256 amountOut;\\n if (tokenIn == Utils.NATIVE_ADDRESS) {\\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\\n } else {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IERC20(tokenIn).approveSafe(pool, amountIn);\\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n else {\\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\\n amountOut = balanceAfter - balanceBefore;\\n }\\n }\\n\\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\\n }\\n}\\n\",\"keccak256\":\"0xcd53a7f473f1847d44c42777a194203cbff02b8c761cb2935402401f57c918a2\",\"license\":\"UNLICENSED\"},\"contracts/Utils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\n\\nlibrary Utils {\\n using SafeERC20 for IERC20;\\n\\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n /**\\n * @dev returns user's balance of token (or native)\\n */\\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\\n if (token == NATIVE_ADDRESS) return address(user).balance;\\n else return IERC20(token).balanceOf(user);\\n }\\n\\n /**\\n * @dev transfers native with correct revert bubble up\\n */\\n function transferNative(address to, uint256 amount) internal {\\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\\n if (!success) {\\n assembly {\\n revert(add(32, returnBytes), mload(returnBytes))\\n }\\n }\\n }\\n\\n /**\\n * @dev transfers ERC20 or native\\n */\\n function transferAny(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\\n else IERC20(token).safeTransfer(to, amount);\\n }\\n\\n /**\\n * @dev transfers from ERC20 or transfers native\\n */\\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n (bool success, bytes memory data) = address(token).call(\\n abi.encodeWithSelector(token.approve.selector, spender, amount)\\n );\\n return success && (data.length == 0 || abi.decode(data, (bool)));\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \\n * current allowance are not zero simultaniously (USDT for example). \\n * In second case it tries to set allowance to 0, and then back to amount.\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n return approveStable(token, spender, amount) \\n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\\n }\\n}\\n\",\"keccak256\":\"0x8c8439edc00b403abd3f34be75a06b1fe71152644ae9f19488af596bbc534ffe\",\"license\":\"UNLICENSED\"},\"interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\nstruct StrategyData {\\n uint64 strategyStartDate;\\n uint64 targetPercentage;\\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n function strategyData(address token) external view returns (StrategyData memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0x0c12eba7a5b9d22d37ab8883fe22d6a312a90682809dbd11c43f8e6ceaff73bf\",\"license\":\"UNLICENSED\"},\"interfaces/ICurve.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\ninterface ICurve {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\\n}\\n\\ninterface ICurveLegacy {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\\n}\\n\\n\",\"keccak256\":\"0x3d4940b3583e06dde20f12e92d2f6ac573b3f64bdaa1e8f480656a3763852518\",\"license\":\"UNLICENSED\"},\"interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/ITridentCLPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface ITridentCLPool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bool unwrapBento,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x572376b80c86a94692b0e27e6e63790b763295e32ba1f956c1d331fc1296de8d\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IUniswapV2Pair.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Pair {\\n event Approval(address indexed owner, address indexed spender, uint value);\\n event Transfer(address indexed from, address indexed to, uint value);\\n\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function allowance(address owner, address spender) external view returns (uint);\\n\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address to, uint value) external returns (bool);\\n function transferFrom(address from, address to, uint value) external returns (bool);\\n\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n function nonces(address owner) external view returns (uint);\\n\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n event Mint(address indexed sender, uint amount0, uint amount1);\\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\\n event Swap(\\n address indexed sender,\\n uint amount0In,\\n uint amount1In,\\n uint amount0Out,\\n uint amount1Out,\\n address indexed to\\n );\\n event Sync(uint112 reserve0, uint112 reserve1);\\n\\n function MINIMUM_LIQUIDITY() external pure returns (uint);\\n function factory() external view returns (address);\\n function token0() external view returns (address);\\n function token1() external view returns (address);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\\n function price0CumulativeLast() external view returns (uint);\\n function price1CumulativeLast() external view returns (uint);\\n function kLast() external view returns (uint);\\n\\n function mint(address to) external returns (uint liquidity);\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function skim(address to) external;\\n function sync() external;\\n\\n function initialize(address, address) external;\\n}\",\"keccak256\":\"0x08f9a63b34855eec941be8d36a04424f1a1725a2c030373fcef3afeb480ca385\",\"license\":\"GPL-3.0\"},\"interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IUniswapV3Pool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x2a4d7c6120e613f0e95d4dc8c650efb9b59e3c25c64e3e5c0a379281500f0a79\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IWETH.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0xae8529ae159f784b90fdcd0629bd03bf7b68accc81edccac53357ad08406a378\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}", + "bytecode": "0x60a06040526002805461ffff60a01b191661010160a01b1790553480156200002657600080fd5b50604051620040a3380380620040a383398101604081905262000049916200016e565b6200005433620000eb565b6001600160a01b038216608052600280546001600160a01b031916600117905560005b8151811015620000e25760018060008484815181106200009b576200009b62000257565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000d9816200026d565b91505062000077565b50505062000297565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200015357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200018257600080fd5b6200018d836200013b565b602084810151919350906001600160401b0380821115620001ad57600080fd5b818601915086601f830112620001c257600080fd5b815181811115620001d757620001d762000158565b8060051b604051601f19603f83011681018181108582111715620001ff57620001ff62000158565b6040529182528482019250838101850191898311156200021e57600080fd5b938501935b82851015620002475762000237856200013b565b8452938501939285019262000223565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200029057634e487b7160e01b600052601160045260246000fd5b5060010190565b608051613da3620003006000396000818161018d01528181611798015281816127380152818161279d01528181612807015281816128cc0152818161297901528181612a5d01528181612b6401528181612c1001528181612cdf0152612df10152613da36000f3fe6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "deployedBytecode": "0x6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "devdoc": { + "author": "Ilya Lyalin", + "kind": "dev", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IAlgebraPoolActions#swap call" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the PancakeV3Pool#swap call" + } + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "route": "Route to process", + "to": "Where to transfer output tokens", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IUniswapV3PoolActions#swap call" + } + } + }, + "title": "A route processor for the Sushi Aggregator", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IAlgebraPool#swap." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via PancakeV3Pool#swap." + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "notice": "Processes the route generated off-chain. Has a lock" + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value of input tokens to and then processes the route" + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "processes the route and sends amount of output token to " + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value to and then processes the route" + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 1060, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "priviledgedUsers", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 1062, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "lastCalledPool", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 1065, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "unlocked", + "offset": 20, + "slot": "2", + "type": "t_uint8" + }, + { + "astId": 1068, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "paused", + "offset": 21, + "slot": "2", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/fantom/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json b/protocols/route-processor/deployments/fantom/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json new file mode 100644 index 0000000000..01826e7b93 --- /dev/null +++ b/protocols/route-processor/deployments/fantom/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json @@ -0,0 +1,80 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" + }, + "contracts/InputStream.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" + }, + "contracts/RouteProcessor5.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" + }, + "contracts/Utils.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "interfaces/IBentoBoxMinimal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" + }, + "interfaces/ICurve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" + }, + "interfaces/IPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" + }, + "interfaces/ITridentCLPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/filecoin/RouteProcessor5.json b/protocols/route-processor/deployments/filecoin/RouteProcessor5.json new file mode 100644 index 0000000000..7f26281134 --- /dev/null +++ b/protocols/route-processor/deployments/filecoin/RouteProcessor5.json @@ -0,0 +1,704 @@ +{ + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_bentoBox", + "type": "address" + }, + { + "internalType": "address[]", + "name": "priviledgedUserList", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "MinimalOutputBalanceViolation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Route", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "algebraSwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bentoBox", + "outputs": [ + { + "internalType": "contract IBentoBoxMinimal", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "pancakeV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "priviledgedUsers", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueInput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "priviledge", + "type": "bool" + } + ], + "name": "setPriviledge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "transferValueAndprocessRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x5c98496219e826b841aab84d23d85732d8a082713492ac054fadf80acd9b4cc1", + "receipt": { + "to": null, + "from": "0x282607716D9B4fDD0B094d5864fac56313f5e665", + "contractAddress": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "transactionIndex": 40, + "gasUsed": "130582919", + "logsBloom": "0x81b330410005006423480278c48021a01c0960104500110a04c30200e000040a8c00ba06b40482130810020a0006902d082240402a212d00413841c002fc0200a01b50b20111a80a2808502a84304320080128130044030001256423909300521104500842040f0a029000c70d00081762021200800804a209213b90d028404a80430809055010411a2220c2120200120090926140f2509a041420c0000810400205040cc2a8048412884a108111200312100081000298254452413212180091e080054a04002221830412061d142010b820808800000010a14d060a40522890821109a0cc94000c028010ade21044588012000062301440064d180da1409601", + "blockHash": "0xc879e11400875f77cb8f91c82cccd33bfd28d6a36cce637f176baf168b22c398", + "transactionHash": "0x5c98496219e826b841aab84d23d85732d8a082713492ac054fadf80acd9b4cc1", + "logs": [ + { + "transactionIndex": 40, + "blockNumber": 4131206, + "transactionHash": "0x5c98496219e826b841aab84d23d85732d8a082713492ac054fadf80acd9b4cc1", + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000282607716d9b4fdd0b094d5864fac56313f5e665" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0xc879e11400875f77cb8f91c82cccd33bfd28d6a36cce637f176baf168b22c398" + } + ], + "blockNumber": 4131206, + "cumulativeGasUsed": "0", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000000", + [] + ], + "numDeployments": 1, + "solcInputHash": "e556d43a3caf4f1fb4f12d632d103b28", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bentoBox\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"priviledgedUserList\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"MinimalOutputBalanceViolation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"Route\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"algebraSwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"pancakeV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"priviledgedUsers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"priviledge\",\"type\":\"bool\"}],\"name\":\"setPriviledge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"transferValueAndprocessRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"Ilya Lyalin\",\"kind\":\"dev\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IAlgebraPoolActions#swap call\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the PancakeV3Pool#swap call\"}},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"route\":\"Route to process\",\"to\":\"Where to transfer output tokens\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IUniswapV3PoolActions#swap call\"}}},\"title\":\"A route processor for the Sushi Aggregator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\"},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Processes the route generated off-chain. Has a lock\"},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value of input tokens to and then processes the route\"},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"processes the route and sends amount of output token to \"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value to and then processes the route\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RouteProcessor5.sol\":\"RouteProcessor5\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\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 Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.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 function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\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\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\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 * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\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\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/InputStream.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\n/** @notice Simple read stream */\\nlibrary InputStream {\\n\\n /** @notice Creates stream from data\\n * @param data data\\n */\\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\\n assembly {\\n stream := mload(0x40)\\n mstore(0x40, add(stream, 64))\\n mstore(stream, data)\\n let length := mload(data)\\n mstore(add(stream, 32), add(data, length))\\n }\\n }\\n\\n /** @notice Checks if stream is not empty\\n * @param stream stream\\n */\\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\\n uint256 pos;\\n uint256 finish;\\n assembly {\\n pos := mload(stream)\\n finish := mload(add(stream, 32))\\n }\\n return pos < finish;\\n }\\n\\n /** @notice Reads uint8 from the stream\\n * @param stream stream\\n */\\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 1)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint16 from the stream\\n * @param stream stream\\n */\\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 2)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint24 from the stream\\n * @param stream stream\\n */\\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 3)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint32 from the stream\\n * @param stream stream\\n */\\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 4)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint256 from the stream\\n * @param stream stream\\n */\\n function readUint(uint256 stream) internal pure returns (uint256 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes32 from the stream\\n * @param stream stream\\n */\\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads address from the stream\\n * @param stream stream\\n */\\n function readAddress(uint256 stream) internal pure returns (address res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 20)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes from the stream\\n * @param stream stream\\n */\\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\\n assembly {\\n let pos := mload(stream)\\n res := add(pos, 32)\\n let length := mload(res)\\n mstore(stream, add(res, length))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x24e24bd0e49cbddacbf3b26bcd4bdffac63d11f3259bc05bc93c0835e8ff5300\",\"license\":\"UNLICENSED\"},\"contracts/RouteProcessor5.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '../interfaces/IUniswapV2Pair.sol';\\nimport '../interfaces/IUniswapV3Pool.sol';\\nimport '../interfaces/ITridentCLPool.sol';\\nimport '../interfaces/IBentoBoxMinimal.sol';\\nimport '../interfaces/IPool.sol';\\nimport '../interfaces/IWETH.sol';\\nimport '../interfaces/ICurve.sol';\\nimport './InputStream.sol';\\nimport './Utils.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\\n\\nuint8 constant LOCKED = 2;\\nuint8 constant NOT_LOCKED = 1;\\nuint8 constant PAUSED = 2;\\nuint8 constant NOT_PAUSED = 1;\\n\\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\nuint160 constant MIN_SQRT_RATIO = 4295128739;\\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n/// @title A route processor for the Sushi Aggregator\\n/// @author Ilya Lyalin\\ncontract RouteProcessor5 is Ownable {\\n using SafeERC20 for IERC20;\\n using Utils for IERC20;\\n using Utils for address;\\n using SafeERC20 for IERC20Permit;\\n using InputStream for uint256;\\n\\n event Route(\\n address indexed from, \\n address to, \\n address indexed tokenIn, \\n address indexed tokenOut, \\n uint256 amountIn, \\n uint256 amountOutMin,\\n uint256 amountOut\\n );\\n\\n error MinimalOutputBalanceViolation(uint256 amountOut);\\n\\n IBentoBoxMinimal public immutable bentoBox;\\n mapping (address => bool) public priviledgedUsers;\\n address private lastCalledPool;\\n\\n uint8 private unlocked = NOT_LOCKED;\\n uint8 private paused = NOT_PAUSED;\\n modifier lock() {\\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\\n unlocked = LOCKED;\\n _;\\n unlocked = NOT_LOCKED;\\n }\\n\\n modifier onlyOwnerOrPriviledgedUser() {\\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \\\"RP: caller is not the owner or a privileged user\\\");\\n _;\\n }\\n\\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\\n bentoBox = IBentoBoxMinimal(_bentoBox);\\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n\\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\\n priviledgedUsers[priviledgedUserList[i]] = true;\\n }\\n }\\n\\n function setPriviledge(address user, bool priviledge) external onlyOwner {\\n priviledgedUsers[user] = priviledge;\\n }\\n\\n function pause() external onlyOwnerOrPriviledgedUser {\\n paused = PAUSED;\\n }\\n\\n function resume() external onlyOwnerOrPriviledgedUser {\\n paused = NOT_PAUSED;\\n }\\n\\n /// @notice For native unwrapping\\n receive() external payable {}\\n\\n /// @notice Processes the route generated off-chain. Has a lock\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @param to Where to transfer output tokens\\n /// @param route Route to process\\n /// @return amountOut Actual amount of the output token\\n function processRoute(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function transferValueAndprocessRoute(\\n address transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n transferValueTo.transferNative(amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value of input tokens to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueInput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n \\n /// @notice processes the route and sends amount of output token to \\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueOutput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\\n }\\n\\n /// @notice Processes the route generated off-chain\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteInternal(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) private returns (uint256 amountOut) {\\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\\n\\n uint256 realAmountIn = amountIn;\\n {\\n uint256 step = 0;\\n uint256 stream = InputStream.createStream(route);\\n while (stream.isNotEmpty()) {\\n uint8 commandCode = stream.readUint8();\\n if (commandCode == 1) {\\n uint256 usedAmount = processMyERC20(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 2) processUserERC20(stream, amountIn);\\n else if (commandCode == 3) {\\n uint256 usedAmount = processNative(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 4) processOnePool(stream);\\n else if (commandCode == 5) processInsideBento(stream);\\n else if (commandCode == 6) applyPermit(tokenIn, stream);\\n else revert('RouteProcessor: Unknown command code');\\n ++step;\\n }\\n }\\n\\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\\n if (tokenIn != Utils.NATIVE_ADDRESS)\\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\\n \\n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\\n\\n amountOut = balanceOutFinal - balanceOutInitial;\\n\\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\\n }\\n\\n /// @notice Applies ERC-2612 permit\\n /// @param tokenIn permitted token\\n /// @param stream Streamed program\\n function applyPermit(address tokenIn, uint256 stream) private {\\n uint256 value = stream.readUint();\\n uint256 deadline = stream.readUint();\\n uint8 v = stream.readUint8();\\n bytes32 r = stream.readBytes32();\\n bytes32 s = stream.readBytes32();\\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\\n }\\n }\\n\\n /// @notice Processes native coin: call swap for all pools that swap from native coin\\n /// @param stream Streamed program\\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\\n amountTotal = address(this).balance;\\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token from this contract balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\\n address token = stream.readAddress();\\n amountTotal = IERC20(token).balanceOf(address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n \\n /// @notice Processes ERC20 token from msg.sender balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n /// @param amountTotal Amount of tokens to take from msg.sender\\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\\n address token = stream.readAddress();\\n distributeAndSwap(stream, msg.sender, token, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token for cases when the token has only one output pool\\n /// @notice In this case liquidity is already at pool balance. This is an optimization\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processOnePool(uint256 stream) private {\\n address token = stream.readAddress();\\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\\n }\\n\\n /// @notice Processes Bento tokens \\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processInsideBento(uint256 stream) private {\\n address token = stream.readAddress();\\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n\\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountTotal Total amount of tokenIn for swaps \\n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\\n uint8 num = stream.readUint8();\\n unchecked {\\n for (uint256 i = 0; i < num; ++i) {\\n uint16 share = stream.readUint16();\\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\\n amountTotal -= amount;\\n swap(stream, from, tokenIn, amount);\\n }\\n }\\n }\\n\\n /// @notice Makes swap\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 poolType = stream.readUint8();\\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\\n else revert('RouteProcessor: Unknown pool type');\\n }\\n\\n /// @notice Wraps/unwraps native token\\n /// @param stream [direction & fake, recipient, wrapToken?]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 directionAndFake = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (directionAndFake & 1 == 1) { // wrap native\\n address wrapToken = stream.readAddress();\\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\\n } else { // unwrap native\\n if (directionAndFake & 2 == 0) {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IWETH(tokenIn).withdraw(amountIn);\\n }\\n to.transferNative(amountIn);\\n }\\n }\\n\\n /// @notice Bridge/unbridge tokens to/from Bento\\n /// @param stream [direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (direction > 0) { // outside to Bento\\n // deposit to arbitrary recipient is possible only from address(bentoBox)\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\\n else {\\n // tokens already are at address(bentoBox)\\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\\n bentoBox.strategyData(tokenIn).balance -\\n bentoBox.totals(tokenIn).elastic;\\n }\\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\\n } else { // Bento to outside\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\\n }\\n }\\n\\n /// @notice UniswapV2 pool swap\\n /// @param stream [pool, direction, recipient, fee]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\\n\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\\n\\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\\n\\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\\n }\\n\\n /// @notice Trident pool swap\\n /// @param stream [pool, swapData]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bytes memory swapData = stream.readBytes();\\n\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, pool, amountIn);\\n }\\n \\n IPool(pool).swap(swapData);\\n }\\n\\n /// @notice UniswapV3 pool swap\\n /// @param stream [pool, direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bool zeroForOne = stream.readUint8() > 0;\\n address recipient = stream.readAddress();\\n\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\\n\\n lastCalledPool = pool;\\n IUniswapV3Pool(pool).swap(\\n recipient,\\n zeroForOne,\\n int256(amountIn),\\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\\n abi.encode(tokenIn)\\n );\\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) public {\\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\\n \\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n (address tokenIn) = abi.decode(data, (address));\\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\\n function algebraSwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\\n function pancakeV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 poolType = stream.readUint8();\\n int128 fromIndex = int8(stream.readUint8());\\n int128 toIndex = int8(stream.readUint8());\\n address to = stream.readAddress();\\n address tokenOut = stream.readAddress();\\n\\n uint256 amountOut;\\n if (tokenIn == Utils.NATIVE_ADDRESS) {\\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\\n } else {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IERC20(tokenIn).approveSafe(pool, amountIn);\\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n else {\\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\\n amountOut = balanceAfter - balanceBefore;\\n }\\n }\\n\\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\\n }\\n}\\n\",\"keccak256\":\"0xcd53a7f473f1847d44c42777a194203cbff02b8c761cb2935402401f57c918a2\",\"license\":\"UNLICENSED\"},\"contracts/Utils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\n\\nlibrary Utils {\\n using SafeERC20 for IERC20;\\n\\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n /**\\n * @dev returns user's balance of token (or native)\\n */\\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\\n if (token == NATIVE_ADDRESS) return address(user).balance;\\n else return IERC20(token).balanceOf(user);\\n }\\n\\n /**\\n * @dev transfers native with correct revert bubble up\\n */\\n function transferNative(address to, uint256 amount) internal {\\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\\n if (!success) {\\n assembly {\\n revert(add(32, returnBytes), mload(returnBytes))\\n }\\n }\\n }\\n\\n /**\\n * @dev transfers ERC20 or native\\n */\\n function transferAny(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\\n else IERC20(token).safeTransfer(to, amount);\\n }\\n\\n /**\\n * @dev transfers from ERC20 or transfers native\\n */\\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n (bool success, bytes memory data) = address(token).call(\\n abi.encodeWithSelector(token.approve.selector, spender, amount)\\n );\\n return success && (data.length == 0 || abi.decode(data, (bool)));\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \\n * current allowance are not zero simultaniously (USDT for example). \\n * In second case it tries to set allowance to 0, and then back to amount.\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n return approveStable(token, spender, amount) \\n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\\n }\\n}\\n\",\"keccak256\":\"0x8c8439edc00b403abd3f34be75a06b1fe71152644ae9f19488af596bbc534ffe\",\"license\":\"UNLICENSED\"},\"interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\nstruct StrategyData {\\n uint64 strategyStartDate;\\n uint64 targetPercentage;\\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n function strategyData(address token) external view returns (StrategyData memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0x0c12eba7a5b9d22d37ab8883fe22d6a312a90682809dbd11c43f8e6ceaff73bf\",\"license\":\"UNLICENSED\"},\"interfaces/ICurve.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\ninterface ICurve {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\\n}\\n\\ninterface ICurveLegacy {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\\n}\\n\\n\",\"keccak256\":\"0x3d4940b3583e06dde20f12e92d2f6ac573b3f64bdaa1e8f480656a3763852518\",\"license\":\"UNLICENSED\"},\"interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/ITridentCLPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface ITridentCLPool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bool unwrapBento,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x572376b80c86a94692b0e27e6e63790b763295e32ba1f956c1d331fc1296de8d\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IUniswapV2Pair.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Pair {\\n event Approval(address indexed owner, address indexed spender, uint value);\\n event Transfer(address indexed from, address indexed to, uint value);\\n\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function allowance(address owner, address spender) external view returns (uint);\\n\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address to, uint value) external returns (bool);\\n function transferFrom(address from, address to, uint value) external returns (bool);\\n\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n function nonces(address owner) external view returns (uint);\\n\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n event Mint(address indexed sender, uint amount0, uint amount1);\\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\\n event Swap(\\n address indexed sender,\\n uint amount0In,\\n uint amount1In,\\n uint amount0Out,\\n uint amount1Out,\\n address indexed to\\n );\\n event Sync(uint112 reserve0, uint112 reserve1);\\n\\n function MINIMUM_LIQUIDITY() external pure returns (uint);\\n function factory() external view returns (address);\\n function token0() external view returns (address);\\n function token1() external view returns (address);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\\n function price0CumulativeLast() external view returns (uint);\\n function price1CumulativeLast() external view returns (uint);\\n function kLast() external view returns (uint);\\n\\n function mint(address to) external returns (uint liquidity);\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function skim(address to) external;\\n function sync() external;\\n\\n function initialize(address, address) external;\\n}\",\"keccak256\":\"0x08f9a63b34855eec941be8d36a04424f1a1725a2c030373fcef3afeb480ca385\",\"license\":\"GPL-3.0\"},\"interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IUniswapV3Pool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x2a4d7c6120e613f0e95d4dc8c650efb9b59e3c25c64e3e5c0a379281500f0a79\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IWETH.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0xae8529ae159f784b90fdcd0629bd03bf7b68accc81edccac53357ad08406a378\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}", + "bytecode": "0x60a06040526002805461ffff60a01b191661010160a01b1790553480156200002657600080fd5b50604051620040a3380380620040a383398101604081905262000049916200016e565b6200005433620000eb565b6001600160a01b038216608052600280546001600160a01b031916600117905560005b8151811015620000e25760018060008484815181106200009b576200009b62000257565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000d9816200026d565b91505062000077565b50505062000297565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200015357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200018257600080fd5b6200018d836200013b565b602084810151919350906001600160401b0380821115620001ad57600080fd5b818601915086601f830112620001c257600080fd5b815181811115620001d757620001d762000158565b8060051b604051601f19603f83011681018181108582111715620001ff57620001ff62000158565b6040529182528482019250838101850191898311156200021e57600080fd5b938501935b82851015620002475762000237856200013b565b8452938501939285019262000223565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200029057634e487b7160e01b600052601160045260246000fd5b5060010190565b608051613da3620003006000396000818161018d01528181611798015281816127380152818161279d01528181612807015281816128cc0152818161297901528181612a5d01528181612b6401528181612c1001528181612cdf0152612df10152613da36000f3fe6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "deployedBytecode": "0x6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "devdoc": { + "author": "Ilya Lyalin", + "kind": "dev", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IAlgebraPoolActions#swap call" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the PancakeV3Pool#swap call" + } + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "route": "Route to process", + "to": "Where to transfer output tokens", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IUniswapV3PoolActions#swap call" + } + } + }, + "title": "A route processor for the Sushi Aggregator", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IAlgebraPool#swap." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via PancakeV3Pool#swap." + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "notice": "Processes the route generated off-chain. Has a lock" + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value of input tokens to and then processes the route" + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "processes the route and sends amount of output token to " + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value to and then processes the route" + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 1060, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "priviledgedUsers", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 1062, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "lastCalledPool", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 1065, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "unlocked", + "offset": 20, + "slot": "2", + "type": "t_uint8" + }, + { + "astId": 1068, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "paused", + "offset": 21, + "slot": "2", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/filecoin/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json b/protocols/route-processor/deployments/filecoin/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json new file mode 100644 index 0000000000..01826e7b93 --- /dev/null +++ b/protocols/route-processor/deployments/filecoin/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json @@ -0,0 +1,80 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" + }, + "contracts/InputStream.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" + }, + "contracts/RouteProcessor5.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" + }, + "contracts/Utils.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "interfaces/IBentoBoxMinimal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" + }, + "interfaces/ICurve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" + }, + "interfaces/IPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" + }, + "interfaces/ITridentCLPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/fuse/RouteProcessor5.json b/protocols/route-processor/deployments/fuse/RouteProcessor5.json new file mode 100644 index 0000000000..0a640797f7 --- /dev/null +++ b/protocols/route-processor/deployments/fuse/RouteProcessor5.json @@ -0,0 +1,704 @@ +{ + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_bentoBox", + "type": "address" + }, + { + "internalType": "address[]", + "name": "priviledgedUserList", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "MinimalOutputBalanceViolation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Route", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "algebraSwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bentoBox", + "outputs": [ + { + "internalType": "contract IBentoBoxMinimal", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "pancakeV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "priviledgedUsers", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueInput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "priviledge", + "type": "bool" + } + ], + "name": "setPriviledge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "transferValueAndprocessRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x120dfa23cda1a02a5375c60787af23b30283a4d56aa95d1b53722cb071f7b3e5", + "receipt": { + "to": null, + "from": "0x282607716D9B4fDD0B094d5864fac56313f5e665", + "contractAddress": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "transactionIndex": 2, + "gasUsed": "3488833", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000020000000000000000000000000000000000000001000000000000000000000000000000000000000000040000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000000000000000000000000000", + "blockHash": "0xa8b5d2a76b89429bae59fd37e39a064a3b3ddf9f847f6466aa85ba845d77085e", + "transactionHash": "0x120dfa23cda1a02a5375c60787af23b30283a4d56aa95d1b53722cb071f7b3e5", + "logs": [ + { + "transactionIndex": 2, + "blockNumber": 30820098, + "transactionHash": "0x120dfa23cda1a02a5375c60787af23b30283a4d56aa95d1b53722cb071f7b3e5", + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000282607716d9b4fdd0b094d5864fac56313f5e665" + ], + "data": "0x", + "logIndex": 4, + "blockHash": "0xa8b5d2a76b89429bae59fd37e39a064a3b3ddf9f847f6466aa85ba845d77085e" + } + ], + "blockNumber": 30820098, + "cumulativeGasUsed": "3693454", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000000", + [] + ], + "numDeployments": 1, + "solcInputHash": "e556d43a3caf4f1fb4f12d632d103b28", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bentoBox\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"priviledgedUserList\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"MinimalOutputBalanceViolation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"Route\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"algebraSwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"pancakeV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"priviledgedUsers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"priviledge\",\"type\":\"bool\"}],\"name\":\"setPriviledge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"transferValueAndprocessRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"Ilya Lyalin\",\"kind\":\"dev\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IAlgebraPoolActions#swap call\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the PancakeV3Pool#swap call\"}},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"route\":\"Route to process\",\"to\":\"Where to transfer output tokens\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IUniswapV3PoolActions#swap call\"}}},\"title\":\"A route processor for the Sushi Aggregator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\"},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Processes the route generated off-chain. Has a lock\"},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value of input tokens to and then processes the route\"},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"processes the route and sends amount of output token to \"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value to and then processes the route\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RouteProcessor5.sol\":\"RouteProcessor5\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\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 Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.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 function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\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\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\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 * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\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\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/InputStream.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\n/** @notice Simple read stream */\\nlibrary InputStream {\\n\\n /** @notice Creates stream from data\\n * @param data data\\n */\\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\\n assembly {\\n stream := mload(0x40)\\n mstore(0x40, add(stream, 64))\\n mstore(stream, data)\\n let length := mload(data)\\n mstore(add(stream, 32), add(data, length))\\n }\\n }\\n\\n /** @notice Checks if stream is not empty\\n * @param stream stream\\n */\\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\\n uint256 pos;\\n uint256 finish;\\n assembly {\\n pos := mload(stream)\\n finish := mload(add(stream, 32))\\n }\\n return pos < finish;\\n }\\n\\n /** @notice Reads uint8 from the stream\\n * @param stream stream\\n */\\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 1)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint16 from the stream\\n * @param stream stream\\n */\\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 2)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint24 from the stream\\n * @param stream stream\\n */\\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 3)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint32 from the stream\\n * @param stream stream\\n */\\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 4)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint256 from the stream\\n * @param stream stream\\n */\\n function readUint(uint256 stream) internal pure returns (uint256 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes32 from the stream\\n * @param stream stream\\n */\\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads address from the stream\\n * @param stream stream\\n */\\n function readAddress(uint256 stream) internal pure returns (address res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 20)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes from the stream\\n * @param stream stream\\n */\\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\\n assembly {\\n let pos := mload(stream)\\n res := add(pos, 32)\\n let length := mload(res)\\n mstore(stream, add(res, length))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x24e24bd0e49cbddacbf3b26bcd4bdffac63d11f3259bc05bc93c0835e8ff5300\",\"license\":\"UNLICENSED\"},\"contracts/RouteProcessor5.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '../interfaces/IUniswapV2Pair.sol';\\nimport '../interfaces/IUniswapV3Pool.sol';\\nimport '../interfaces/ITridentCLPool.sol';\\nimport '../interfaces/IBentoBoxMinimal.sol';\\nimport '../interfaces/IPool.sol';\\nimport '../interfaces/IWETH.sol';\\nimport '../interfaces/ICurve.sol';\\nimport './InputStream.sol';\\nimport './Utils.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\\n\\nuint8 constant LOCKED = 2;\\nuint8 constant NOT_LOCKED = 1;\\nuint8 constant PAUSED = 2;\\nuint8 constant NOT_PAUSED = 1;\\n\\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\nuint160 constant MIN_SQRT_RATIO = 4295128739;\\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n/// @title A route processor for the Sushi Aggregator\\n/// @author Ilya Lyalin\\ncontract RouteProcessor5 is Ownable {\\n using SafeERC20 for IERC20;\\n using Utils for IERC20;\\n using Utils for address;\\n using SafeERC20 for IERC20Permit;\\n using InputStream for uint256;\\n\\n event Route(\\n address indexed from, \\n address to, \\n address indexed tokenIn, \\n address indexed tokenOut, \\n uint256 amountIn, \\n uint256 amountOutMin,\\n uint256 amountOut\\n );\\n\\n error MinimalOutputBalanceViolation(uint256 amountOut);\\n\\n IBentoBoxMinimal public immutable bentoBox;\\n mapping (address => bool) public priviledgedUsers;\\n address private lastCalledPool;\\n\\n uint8 private unlocked = NOT_LOCKED;\\n uint8 private paused = NOT_PAUSED;\\n modifier lock() {\\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\\n unlocked = LOCKED;\\n _;\\n unlocked = NOT_LOCKED;\\n }\\n\\n modifier onlyOwnerOrPriviledgedUser() {\\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \\\"RP: caller is not the owner or a privileged user\\\");\\n _;\\n }\\n\\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\\n bentoBox = IBentoBoxMinimal(_bentoBox);\\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n\\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\\n priviledgedUsers[priviledgedUserList[i]] = true;\\n }\\n }\\n\\n function setPriviledge(address user, bool priviledge) external onlyOwner {\\n priviledgedUsers[user] = priviledge;\\n }\\n\\n function pause() external onlyOwnerOrPriviledgedUser {\\n paused = PAUSED;\\n }\\n\\n function resume() external onlyOwnerOrPriviledgedUser {\\n paused = NOT_PAUSED;\\n }\\n\\n /// @notice For native unwrapping\\n receive() external payable {}\\n\\n /// @notice Processes the route generated off-chain. Has a lock\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @param to Where to transfer output tokens\\n /// @param route Route to process\\n /// @return amountOut Actual amount of the output token\\n function processRoute(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function transferValueAndprocessRoute(\\n address transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n transferValueTo.transferNative(amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value of input tokens to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueInput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n \\n /// @notice processes the route and sends amount of output token to \\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueOutput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\\n }\\n\\n /// @notice Processes the route generated off-chain\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteInternal(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) private returns (uint256 amountOut) {\\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\\n\\n uint256 realAmountIn = amountIn;\\n {\\n uint256 step = 0;\\n uint256 stream = InputStream.createStream(route);\\n while (stream.isNotEmpty()) {\\n uint8 commandCode = stream.readUint8();\\n if (commandCode == 1) {\\n uint256 usedAmount = processMyERC20(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 2) processUserERC20(stream, amountIn);\\n else if (commandCode == 3) {\\n uint256 usedAmount = processNative(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 4) processOnePool(stream);\\n else if (commandCode == 5) processInsideBento(stream);\\n else if (commandCode == 6) applyPermit(tokenIn, stream);\\n else revert('RouteProcessor: Unknown command code');\\n ++step;\\n }\\n }\\n\\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\\n if (tokenIn != Utils.NATIVE_ADDRESS)\\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\\n \\n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\\n\\n amountOut = balanceOutFinal - balanceOutInitial;\\n\\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\\n }\\n\\n /// @notice Applies ERC-2612 permit\\n /// @param tokenIn permitted token\\n /// @param stream Streamed program\\n function applyPermit(address tokenIn, uint256 stream) private {\\n uint256 value = stream.readUint();\\n uint256 deadline = stream.readUint();\\n uint8 v = stream.readUint8();\\n bytes32 r = stream.readBytes32();\\n bytes32 s = stream.readBytes32();\\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\\n }\\n }\\n\\n /// @notice Processes native coin: call swap for all pools that swap from native coin\\n /// @param stream Streamed program\\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\\n amountTotal = address(this).balance;\\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token from this contract balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\\n address token = stream.readAddress();\\n amountTotal = IERC20(token).balanceOf(address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n \\n /// @notice Processes ERC20 token from msg.sender balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n /// @param amountTotal Amount of tokens to take from msg.sender\\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\\n address token = stream.readAddress();\\n distributeAndSwap(stream, msg.sender, token, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token for cases when the token has only one output pool\\n /// @notice In this case liquidity is already at pool balance. This is an optimization\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processOnePool(uint256 stream) private {\\n address token = stream.readAddress();\\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\\n }\\n\\n /// @notice Processes Bento tokens \\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processInsideBento(uint256 stream) private {\\n address token = stream.readAddress();\\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n\\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountTotal Total amount of tokenIn for swaps \\n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\\n uint8 num = stream.readUint8();\\n unchecked {\\n for (uint256 i = 0; i < num; ++i) {\\n uint16 share = stream.readUint16();\\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\\n amountTotal -= amount;\\n swap(stream, from, tokenIn, amount);\\n }\\n }\\n }\\n\\n /// @notice Makes swap\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 poolType = stream.readUint8();\\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\\n else revert('RouteProcessor: Unknown pool type');\\n }\\n\\n /// @notice Wraps/unwraps native token\\n /// @param stream [direction & fake, recipient, wrapToken?]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 directionAndFake = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (directionAndFake & 1 == 1) { // wrap native\\n address wrapToken = stream.readAddress();\\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\\n } else { // unwrap native\\n if (directionAndFake & 2 == 0) {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IWETH(tokenIn).withdraw(amountIn);\\n }\\n to.transferNative(amountIn);\\n }\\n }\\n\\n /// @notice Bridge/unbridge tokens to/from Bento\\n /// @param stream [direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (direction > 0) { // outside to Bento\\n // deposit to arbitrary recipient is possible only from address(bentoBox)\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\\n else {\\n // tokens already are at address(bentoBox)\\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\\n bentoBox.strategyData(tokenIn).balance -\\n bentoBox.totals(tokenIn).elastic;\\n }\\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\\n } else { // Bento to outside\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\\n }\\n }\\n\\n /// @notice UniswapV2 pool swap\\n /// @param stream [pool, direction, recipient, fee]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\\n\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\\n\\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\\n\\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\\n }\\n\\n /// @notice Trident pool swap\\n /// @param stream [pool, swapData]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bytes memory swapData = stream.readBytes();\\n\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, pool, amountIn);\\n }\\n \\n IPool(pool).swap(swapData);\\n }\\n\\n /// @notice UniswapV3 pool swap\\n /// @param stream [pool, direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bool zeroForOne = stream.readUint8() > 0;\\n address recipient = stream.readAddress();\\n\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\\n\\n lastCalledPool = pool;\\n IUniswapV3Pool(pool).swap(\\n recipient,\\n zeroForOne,\\n int256(amountIn),\\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\\n abi.encode(tokenIn)\\n );\\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) public {\\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\\n \\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n (address tokenIn) = abi.decode(data, (address));\\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\\n function algebraSwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\\n function pancakeV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 poolType = stream.readUint8();\\n int128 fromIndex = int8(stream.readUint8());\\n int128 toIndex = int8(stream.readUint8());\\n address to = stream.readAddress();\\n address tokenOut = stream.readAddress();\\n\\n uint256 amountOut;\\n if (tokenIn == Utils.NATIVE_ADDRESS) {\\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\\n } else {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IERC20(tokenIn).approveSafe(pool, amountIn);\\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n else {\\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\\n amountOut = balanceAfter - balanceBefore;\\n }\\n }\\n\\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\\n }\\n}\\n\",\"keccak256\":\"0xcd53a7f473f1847d44c42777a194203cbff02b8c761cb2935402401f57c918a2\",\"license\":\"UNLICENSED\"},\"contracts/Utils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\n\\nlibrary Utils {\\n using SafeERC20 for IERC20;\\n\\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n /**\\n * @dev returns user's balance of token (or native)\\n */\\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\\n if (token == NATIVE_ADDRESS) return address(user).balance;\\n else return IERC20(token).balanceOf(user);\\n }\\n\\n /**\\n * @dev transfers native with correct revert bubble up\\n */\\n function transferNative(address to, uint256 amount) internal {\\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\\n if (!success) {\\n assembly {\\n revert(add(32, returnBytes), mload(returnBytes))\\n }\\n }\\n }\\n\\n /**\\n * @dev transfers ERC20 or native\\n */\\n function transferAny(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\\n else IERC20(token).safeTransfer(to, amount);\\n }\\n\\n /**\\n * @dev transfers from ERC20 or transfers native\\n */\\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n (bool success, bytes memory data) = address(token).call(\\n abi.encodeWithSelector(token.approve.selector, spender, amount)\\n );\\n return success && (data.length == 0 || abi.decode(data, (bool)));\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \\n * current allowance are not zero simultaniously (USDT for example). \\n * In second case it tries to set allowance to 0, and then back to amount.\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n return approveStable(token, spender, amount) \\n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\\n }\\n}\\n\",\"keccak256\":\"0x8c8439edc00b403abd3f34be75a06b1fe71152644ae9f19488af596bbc534ffe\",\"license\":\"UNLICENSED\"},\"interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\nstruct StrategyData {\\n uint64 strategyStartDate;\\n uint64 targetPercentage;\\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n function strategyData(address token) external view returns (StrategyData memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0x0c12eba7a5b9d22d37ab8883fe22d6a312a90682809dbd11c43f8e6ceaff73bf\",\"license\":\"UNLICENSED\"},\"interfaces/ICurve.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\ninterface ICurve {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\\n}\\n\\ninterface ICurveLegacy {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\\n}\\n\\n\",\"keccak256\":\"0x3d4940b3583e06dde20f12e92d2f6ac573b3f64bdaa1e8f480656a3763852518\",\"license\":\"UNLICENSED\"},\"interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/ITridentCLPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface ITridentCLPool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bool unwrapBento,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x572376b80c86a94692b0e27e6e63790b763295e32ba1f956c1d331fc1296de8d\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IUniswapV2Pair.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Pair {\\n event Approval(address indexed owner, address indexed spender, uint value);\\n event Transfer(address indexed from, address indexed to, uint value);\\n\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function allowance(address owner, address spender) external view returns (uint);\\n\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address to, uint value) external returns (bool);\\n function transferFrom(address from, address to, uint value) external returns (bool);\\n\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n function nonces(address owner) external view returns (uint);\\n\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n event Mint(address indexed sender, uint amount0, uint amount1);\\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\\n event Swap(\\n address indexed sender,\\n uint amount0In,\\n uint amount1In,\\n uint amount0Out,\\n uint amount1Out,\\n address indexed to\\n );\\n event Sync(uint112 reserve0, uint112 reserve1);\\n\\n function MINIMUM_LIQUIDITY() external pure returns (uint);\\n function factory() external view returns (address);\\n function token0() external view returns (address);\\n function token1() external view returns (address);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\\n function price0CumulativeLast() external view returns (uint);\\n function price1CumulativeLast() external view returns (uint);\\n function kLast() external view returns (uint);\\n\\n function mint(address to) external returns (uint liquidity);\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function skim(address to) external;\\n function sync() external;\\n\\n function initialize(address, address) external;\\n}\",\"keccak256\":\"0x08f9a63b34855eec941be8d36a04424f1a1725a2c030373fcef3afeb480ca385\",\"license\":\"GPL-3.0\"},\"interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IUniswapV3Pool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x2a4d7c6120e613f0e95d4dc8c650efb9b59e3c25c64e3e5c0a379281500f0a79\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IWETH.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0xae8529ae159f784b90fdcd0629bd03bf7b68accc81edccac53357ad08406a378\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}", + "bytecode": "0x60a06040526002805461ffff60a01b191661010160a01b1790553480156200002657600080fd5b50604051620040a3380380620040a383398101604081905262000049916200016e565b6200005433620000eb565b6001600160a01b038216608052600280546001600160a01b031916600117905560005b8151811015620000e25760018060008484815181106200009b576200009b62000257565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000d9816200026d565b91505062000077565b50505062000297565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200015357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200018257600080fd5b6200018d836200013b565b602084810151919350906001600160401b0380821115620001ad57600080fd5b818601915086601f830112620001c257600080fd5b815181811115620001d757620001d762000158565b8060051b604051601f19603f83011681018181108582111715620001ff57620001ff62000158565b6040529182528482019250838101850191898311156200021e57600080fd5b938501935b82851015620002475762000237856200013b565b8452938501939285019262000223565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200029057634e487b7160e01b600052601160045260246000fd5b5060010190565b608051613da3620003006000396000818161018d01528181611798015281816127380152818161279d01528181612807015281816128cc0152818161297901528181612a5d01528181612b6401528181612c1001528181612cdf0152612df10152613da36000f3fe6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "deployedBytecode": "0x6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "devdoc": { + "author": "Ilya Lyalin", + "kind": "dev", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IAlgebraPoolActions#swap call" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the PancakeV3Pool#swap call" + } + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "route": "Route to process", + "to": "Where to transfer output tokens", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IUniswapV3PoolActions#swap call" + } + } + }, + "title": "A route processor for the Sushi Aggregator", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IAlgebraPool#swap." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via PancakeV3Pool#swap." + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "notice": "Processes the route generated off-chain. Has a lock" + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value of input tokens to and then processes the route" + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "processes the route and sends amount of output token to " + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value to and then processes the route" + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 1060, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "priviledgedUsers", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 1062, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "lastCalledPool", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 1065, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "unlocked", + "offset": 20, + "slot": "2", + "type": "t_uint8" + }, + { + "astId": 1068, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "paused", + "offset": 21, + "slot": "2", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/fuse/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json b/protocols/route-processor/deployments/fuse/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json new file mode 100644 index 0000000000..01826e7b93 --- /dev/null +++ b/protocols/route-processor/deployments/fuse/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json @@ -0,0 +1,80 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" + }, + "contracts/InputStream.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" + }, + "contracts/RouteProcessor5.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" + }, + "contracts/Utils.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "interfaces/IBentoBoxMinimal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" + }, + "interfaces/ICurve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" + }, + "interfaces/IPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" + }, + "interfaces/ITridentCLPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/gnosis/RouteProcessor5.json b/protocols/route-processor/deployments/gnosis/RouteProcessor5.json new file mode 100644 index 0000000000..ee3a195da8 --- /dev/null +++ b/protocols/route-processor/deployments/gnosis/RouteProcessor5.json @@ -0,0 +1,704 @@ +{ + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_bentoBox", + "type": "address" + }, + { + "internalType": "address[]", + "name": "priviledgedUserList", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "MinimalOutputBalanceViolation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Route", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "algebraSwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bentoBox", + "outputs": [ + { + "internalType": "contract IBentoBoxMinimal", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "pancakeV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "priviledgedUsers", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueInput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "priviledge", + "type": "bool" + } + ], + "name": "setPriviledge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "transferValueAndprocessRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0xcb630263ef5486f0fdeeace2218b6f5ddf2e2e053854b1078f9082cec5d8008f", + "receipt": { + "to": null, + "from": "0x282607716D9B4fDD0B094d5864fac56313f5e665", + "contractAddress": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "transactionIndex": 1, + "gasUsed": "3489875", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000020000000000000000000000000000000000000001000000000000000000000000000000000000000000040000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000000000000000000000000000", + "blockHash": "0xa76af0e87659750d3d0c5a2b50948a8710bc7804641fd1f4bb839834ff374a16", + "transactionHash": "0xcb630263ef5486f0fdeeace2218b6f5ddf2e2e053854b1078f9082cec5d8008f", + "logs": [ + { + "transactionIndex": 1, + "blockNumber": 35209506, + "transactionHash": "0xcb630263ef5486f0fdeeace2218b6f5ddf2e2e053854b1078f9082cec5d8008f", + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000282607716d9b4fdd0b094d5864fac56313f5e665" + ], + "data": "0x", + "logIndex": 9, + "blockHash": "0xa76af0e87659750d3d0c5a2b50948a8710bc7804641fd1f4bb839834ff374a16" + } + ], + "blockNumber": 35209506, + "cumulativeGasUsed": "3815968", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000000", + [] + ], + "numDeployments": 1, + "solcInputHash": "e556d43a3caf4f1fb4f12d632d103b28", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bentoBox\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"priviledgedUserList\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"MinimalOutputBalanceViolation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"Route\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"algebraSwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"pancakeV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"priviledgedUsers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"priviledge\",\"type\":\"bool\"}],\"name\":\"setPriviledge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"transferValueAndprocessRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"Ilya Lyalin\",\"kind\":\"dev\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IAlgebraPoolActions#swap call\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the PancakeV3Pool#swap call\"}},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"route\":\"Route to process\",\"to\":\"Where to transfer output tokens\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IUniswapV3PoolActions#swap call\"}}},\"title\":\"A route processor for the Sushi Aggregator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\"},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Processes the route generated off-chain. Has a lock\"},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value of input tokens to and then processes the route\"},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"processes the route and sends amount of output token to \"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value to and then processes the route\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RouteProcessor5.sol\":\"RouteProcessor5\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\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 Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.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 function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\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\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\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 * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\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\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/InputStream.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\n/** @notice Simple read stream */\\nlibrary InputStream {\\n\\n /** @notice Creates stream from data\\n * @param data data\\n */\\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\\n assembly {\\n stream := mload(0x40)\\n mstore(0x40, add(stream, 64))\\n mstore(stream, data)\\n let length := mload(data)\\n mstore(add(stream, 32), add(data, length))\\n }\\n }\\n\\n /** @notice Checks if stream is not empty\\n * @param stream stream\\n */\\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\\n uint256 pos;\\n uint256 finish;\\n assembly {\\n pos := mload(stream)\\n finish := mload(add(stream, 32))\\n }\\n return pos < finish;\\n }\\n\\n /** @notice Reads uint8 from the stream\\n * @param stream stream\\n */\\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 1)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint16 from the stream\\n * @param stream stream\\n */\\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 2)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint24 from the stream\\n * @param stream stream\\n */\\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 3)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint32 from the stream\\n * @param stream stream\\n */\\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 4)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint256 from the stream\\n * @param stream stream\\n */\\n function readUint(uint256 stream) internal pure returns (uint256 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes32 from the stream\\n * @param stream stream\\n */\\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads address from the stream\\n * @param stream stream\\n */\\n function readAddress(uint256 stream) internal pure returns (address res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 20)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes from the stream\\n * @param stream stream\\n */\\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\\n assembly {\\n let pos := mload(stream)\\n res := add(pos, 32)\\n let length := mload(res)\\n mstore(stream, add(res, length))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x24e24bd0e49cbddacbf3b26bcd4bdffac63d11f3259bc05bc93c0835e8ff5300\",\"license\":\"UNLICENSED\"},\"contracts/RouteProcessor5.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '../interfaces/IUniswapV2Pair.sol';\\nimport '../interfaces/IUniswapV3Pool.sol';\\nimport '../interfaces/ITridentCLPool.sol';\\nimport '../interfaces/IBentoBoxMinimal.sol';\\nimport '../interfaces/IPool.sol';\\nimport '../interfaces/IWETH.sol';\\nimport '../interfaces/ICurve.sol';\\nimport './InputStream.sol';\\nimport './Utils.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\\n\\nuint8 constant LOCKED = 2;\\nuint8 constant NOT_LOCKED = 1;\\nuint8 constant PAUSED = 2;\\nuint8 constant NOT_PAUSED = 1;\\n\\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\nuint160 constant MIN_SQRT_RATIO = 4295128739;\\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n/// @title A route processor for the Sushi Aggregator\\n/// @author Ilya Lyalin\\ncontract RouteProcessor5 is Ownable {\\n using SafeERC20 for IERC20;\\n using Utils for IERC20;\\n using Utils for address;\\n using SafeERC20 for IERC20Permit;\\n using InputStream for uint256;\\n\\n event Route(\\n address indexed from, \\n address to, \\n address indexed tokenIn, \\n address indexed tokenOut, \\n uint256 amountIn, \\n uint256 amountOutMin,\\n uint256 amountOut\\n );\\n\\n error MinimalOutputBalanceViolation(uint256 amountOut);\\n\\n IBentoBoxMinimal public immutable bentoBox;\\n mapping (address => bool) public priviledgedUsers;\\n address private lastCalledPool;\\n\\n uint8 private unlocked = NOT_LOCKED;\\n uint8 private paused = NOT_PAUSED;\\n modifier lock() {\\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\\n unlocked = LOCKED;\\n _;\\n unlocked = NOT_LOCKED;\\n }\\n\\n modifier onlyOwnerOrPriviledgedUser() {\\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \\\"RP: caller is not the owner or a privileged user\\\");\\n _;\\n }\\n\\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\\n bentoBox = IBentoBoxMinimal(_bentoBox);\\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n\\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\\n priviledgedUsers[priviledgedUserList[i]] = true;\\n }\\n }\\n\\n function setPriviledge(address user, bool priviledge) external onlyOwner {\\n priviledgedUsers[user] = priviledge;\\n }\\n\\n function pause() external onlyOwnerOrPriviledgedUser {\\n paused = PAUSED;\\n }\\n\\n function resume() external onlyOwnerOrPriviledgedUser {\\n paused = NOT_PAUSED;\\n }\\n\\n /// @notice For native unwrapping\\n receive() external payable {}\\n\\n /// @notice Processes the route generated off-chain. Has a lock\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @param to Where to transfer output tokens\\n /// @param route Route to process\\n /// @return amountOut Actual amount of the output token\\n function processRoute(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function transferValueAndprocessRoute(\\n address transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n transferValueTo.transferNative(amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value of input tokens to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueInput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n \\n /// @notice processes the route and sends amount of output token to \\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueOutput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\\n }\\n\\n /// @notice Processes the route generated off-chain\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteInternal(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) private returns (uint256 amountOut) {\\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\\n\\n uint256 realAmountIn = amountIn;\\n {\\n uint256 step = 0;\\n uint256 stream = InputStream.createStream(route);\\n while (stream.isNotEmpty()) {\\n uint8 commandCode = stream.readUint8();\\n if (commandCode == 1) {\\n uint256 usedAmount = processMyERC20(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 2) processUserERC20(stream, amountIn);\\n else if (commandCode == 3) {\\n uint256 usedAmount = processNative(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 4) processOnePool(stream);\\n else if (commandCode == 5) processInsideBento(stream);\\n else if (commandCode == 6) applyPermit(tokenIn, stream);\\n else revert('RouteProcessor: Unknown command code');\\n ++step;\\n }\\n }\\n\\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\\n if (tokenIn != Utils.NATIVE_ADDRESS)\\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\\n \\n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\\n\\n amountOut = balanceOutFinal - balanceOutInitial;\\n\\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\\n }\\n\\n /// @notice Applies ERC-2612 permit\\n /// @param tokenIn permitted token\\n /// @param stream Streamed program\\n function applyPermit(address tokenIn, uint256 stream) private {\\n uint256 value = stream.readUint();\\n uint256 deadline = stream.readUint();\\n uint8 v = stream.readUint8();\\n bytes32 r = stream.readBytes32();\\n bytes32 s = stream.readBytes32();\\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\\n }\\n }\\n\\n /// @notice Processes native coin: call swap for all pools that swap from native coin\\n /// @param stream Streamed program\\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\\n amountTotal = address(this).balance;\\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token from this contract balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\\n address token = stream.readAddress();\\n amountTotal = IERC20(token).balanceOf(address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n \\n /// @notice Processes ERC20 token from msg.sender balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n /// @param amountTotal Amount of tokens to take from msg.sender\\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\\n address token = stream.readAddress();\\n distributeAndSwap(stream, msg.sender, token, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token for cases when the token has only one output pool\\n /// @notice In this case liquidity is already at pool balance. This is an optimization\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processOnePool(uint256 stream) private {\\n address token = stream.readAddress();\\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\\n }\\n\\n /// @notice Processes Bento tokens \\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processInsideBento(uint256 stream) private {\\n address token = stream.readAddress();\\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n\\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountTotal Total amount of tokenIn for swaps \\n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\\n uint8 num = stream.readUint8();\\n unchecked {\\n for (uint256 i = 0; i < num; ++i) {\\n uint16 share = stream.readUint16();\\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\\n amountTotal -= amount;\\n swap(stream, from, tokenIn, amount);\\n }\\n }\\n }\\n\\n /// @notice Makes swap\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 poolType = stream.readUint8();\\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\\n else revert('RouteProcessor: Unknown pool type');\\n }\\n\\n /// @notice Wraps/unwraps native token\\n /// @param stream [direction & fake, recipient, wrapToken?]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 directionAndFake = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (directionAndFake & 1 == 1) { // wrap native\\n address wrapToken = stream.readAddress();\\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\\n } else { // unwrap native\\n if (directionAndFake & 2 == 0) {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IWETH(tokenIn).withdraw(amountIn);\\n }\\n to.transferNative(amountIn);\\n }\\n }\\n\\n /// @notice Bridge/unbridge tokens to/from Bento\\n /// @param stream [direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (direction > 0) { // outside to Bento\\n // deposit to arbitrary recipient is possible only from address(bentoBox)\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\\n else {\\n // tokens already are at address(bentoBox)\\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\\n bentoBox.strategyData(tokenIn).balance -\\n bentoBox.totals(tokenIn).elastic;\\n }\\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\\n } else { // Bento to outside\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\\n }\\n }\\n\\n /// @notice UniswapV2 pool swap\\n /// @param stream [pool, direction, recipient, fee]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\\n\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\\n\\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\\n\\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\\n }\\n\\n /// @notice Trident pool swap\\n /// @param stream [pool, swapData]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bytes memory swapData = stream.readBytes();\\n\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, pool, amountIn);\\n }\\n \\n IPool(pool).swap(swapData);\\n }\\n\\n /// @notice UniswapV3 pool swap\\n /// @param stream [pool, direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bool zeroForOne = stream.readUint8() > 0;\\n address recipient = stream.readAddress();\\n\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\\n\\n lastCalledPool = pool;\\n IUniswapV3Pool(pool).swap(\\n recipient,\\n zeroForOne,\\n int256(amountIn),\\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\\n abi.encode(tokenIn)\\n );\\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) public {\\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\\n \\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n (address tokenIn) = abi.decode(data, (address));\\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\\n function algebraSwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\\n function pancakeV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 poolType = stream.readUint8();\\n int128 fromIndex = int8(stream.readUint8());\\n int128 toIndex = int8(stream.readUint8());\\n address to = stream.readAddress();\\n address tokenOut = stream.readAddress();\\n\\n uint256 amountOut;\\n if (tokenIn == Utils.NATIVE_ADDRESS) {\\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\\n } else {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IERC20(tokenIn).approveSafe(pool, amountIn);\\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n else {\\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\\n amountOut = balanceAfter - balanceBefore;\\n }\\n }\\n\\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\\n }\\n}\\n\",\"keccak256\":\"0xcd53a7f473f1847d44c42777a194203cbff02b8c761cb2935402401f57c918a2\",\"license\":\"UNLICENSED\"},\"contracts/Utils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\n\\nlibrary Utils {\\n using SafeERC20 for IERC20;\\n\\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n /**\\n * @dev returns user's balance of token (or native)\\n */\\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\\n if (token == NATIVE_ADDRESS) return address(user).balance;\\n else return IERC20(token).balanceOf(user);\\n }\\n\\n /**\\n * @dev transfers native with correct revert bubble up\\n */\\n function transferNative(address to, uint256 amount) internal {\\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\\n if (!success) {\\n assembly {\\n revert(add(32, returnBytes), mload(returnBytes))\\n }\\n }\\n }\\n\\n /**\\n * @dev transfers ERC20 or native\\n */\\n function transferAny(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\\n else IERC20(token).safeTransfer(to, amount);\\n }\\n\\n /**\\n * @dev transfers from ERC20 or transfers native\\n */\\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n (bool success, bytes memory data) = address(token).call(\\n abi.encodeWithSelector(token.approve.selector, spender, amount)\\n );\\n return success && (data.length == 0 || abi.decode(data, (bool)));\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \\n * current allowance are not zero simultaniously (USDT for example). \\n * In second case it tries to set allowance to 0, and then back to amount.\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n return approveStable(token, spender, amount) \\n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\\n }\\n}\\n\",\"keccak256\":\"0x8c8439edc00b403abd3f34be75a06b1fe71152644ae9f19488af596bbc534ffe\",\"license\":\"UNLICENSED\"},\"interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\nstruct StrategyData {\\n uint64 strategyStartDate;\\n uint64 targetPercentage;\\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n function strategyData(address token) external view returns (StrategyData memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0x0c12eba7a5b9d22d37ab8883fe22d6a312a90682809dbd11c43f8e6ceaff73bf\",\"license\":\"UNLICENSED\"},\"interfaces/ICurve.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\ninterface ICurve {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\\n}\\n\\ninterface ICurveLegacy {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\\n}\\n\\n\",\"keccak256\":\"0x3d4940b3583e06dde20f12e92d2f6ac573b3f64bdaa1e8f480656a3763852518\",\"license\":\"UNLICENSED\"},\"interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/ITridentCLPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface ITridentCLPool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bool unwrapBento,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x572376b80c86a94692b0e27e6e63790b763295e32ba1f956c1d331fc1296de8d\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IUniswapV2Pair.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Pair {\\n event Approval(address indexed owner, address indexed spender, uint value);\\n event Transfer(address indexed from, address indexed to, uint value);\\n\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function allowance(address owner, address spender) external view returns (uint);\\n\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address to, uint value) external returns (bool);\\n function transferFrom(address from, address to, uint value) external returns (bool);\\n\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n function nonces(address owner) external view returns (uint);\\n\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n event Mint(address indexed sender, uint amount0, uint amount1);\\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\\n event Swap(\\n address indexed sender,\\n uint amount0In,\\n uint amount1In,\\n uint amount0Out,\\n uint amount1Out,\\n address indexed to\\n );\\n event Sync(uint112 reserve0, uint112 reserve1);\\n\\n function MINIMUM_LIQUIDITY() external pure returns (uint);\\n function factory() external view returns (address);\\n function token0() external view returns (address);\\n function token1() external view returns (address);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\\n function price0CumulativeLast() external view returns (uint);\\n function price1CumulativeLast() external view returns (uint);\\n function kLast() external view returns (uint);\\n\\n function mint(address to) external returns (uint liquidity);\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function skim(address to) external;\\n function sync() external;\\n\\n function initialize(address, address) external;\\n}\",\"keccak256\":\"0x08f9a63b34855eec941be8d36a04424f1a1725a2c030373fcef3afeb480ca385\",\"license\":\"GPL-3.0\"},\"interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IUniswapV3Pool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x2a4d7c6120e613f0e95d4dc8c650efb9b59e3c25c64e3e5c0a379281500f0a79\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IWETH.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0xae8529ae159f784b90fdcd0629bd03bf7b68accc81edccac53357ad08406a378\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}", + "bytecode": "0x60a06040526002805461ffff60a01b191661010160a01b1790553480156200002657600080fd5b50604051620040a3380380620040a383398101604081905262000049916200016e565b6200005433620000eb565b6001600160a01b038216608052600280546001600160a01b031916600117905560005b8151811015620000e25760018060008484815181106200009b576200009b62000257565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000d9816200026d565b91505062000077565b50505062000297565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200015357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200018257600080fd5b6200018d836200013b565b602084810151919350906001600160401b0380821115620001ad57600080fd5b818601915086601f830112620001c257600080fd5b815181811115620001d757620001d762000158565b8060051b604051601f19603f83011681018181108582111715620001ff57620001ff62000158565b6040529182528482019250838101850191898311156200021e57600080fd5b938501935b82851015620002475762000237856200013b565b8452938501939285019262000223565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200029057634e487b7160e01b600052601160045260246000fd5b5060010190565b608051613da3620003006000396000818161018d01528181611798015281816127380152818161279d01528181612807015281816128cc0152818161297901528181612a5d01528181612b6401528181612c1001528181612cdf0152612df10152613da36000f3fe6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "deployedBytecode": "0x6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "devdoc": { + "author": "Ilya Lyalin", + "kind": "dev", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IAlgebraPoolActions#swap call" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the PancakeV3Pool#swap call" + } + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "route": "Route to process", + "to": "Where to transfer output tokens", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IUniswapV3PoolActions#swap call" + } + } + }, + "title": "A route processor for the Sushi Aggregator", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IAlgebraPool#swap." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via PancakeV3Pool#swap." + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "notice": "Processes the route generated off-chain. Has a lock" + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value of input tokens to and then processes the route" + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "processes the route and sends amount of output token to " + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value to and then processes the route" + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 1060, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "priviledgedUsers", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 1062, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "lastCalledPool", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 1065, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "unlocked", + "offset": 20, + "slot": "2", + "type": "t_uint8" + }, + { + "astId": 1068, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "paused", + "offset": 21, + "slot": "2", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/gnosis/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json b/protocols/route-processor/deployments/gnosis/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json new file mode 100644 index 0000000000..01826e7b93 --- /dev/null +++ b/protocols/route-processor/deployments/gnosis/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json @@ -0,0 +1,80 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" + }, + "contracts/InputStream.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" + }, + "contracts/RouteProcessor5.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" + }, + "contracts/Utils.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "interfaces/IBentoBoxMinimal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" + }, + "interfaces/ICurve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" + }, + "interfaces/IPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" + }, + "interfaces/ITridentCLPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/haqq/RouteProcessor5.json b/protocols/route-processor/deployments/haqq/RouteProcessor5.json new file mode 100644 index 0000000000..04e69d41da --- /dev/null +++ b/protocols/route-processor/deployments/haqq/RouteProcessor5.json @@ -0,0 +1,704 @@ +{ + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_bentoBox", + "type": "address" + }, + { + "internalType": "address[]", + "name": "priviledgedUserList", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "MinimalOutputBalanceViolation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Route", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "algebraSwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bentoBox", + "outputs": [ + { + "internalType": "contract IBentoBoxMinimal", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "pancakeV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "priviledgedUsers", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueInput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "priviledge", + "type": "bool" + } + ], + "name": "setPriviledge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "transferValueAndprocessRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x1863cf5ef646c0917370950b629317c013012d8f4da7ceeb4958f081af3c4487", + "receipt": { + "to": null, + "from": "0x282607716D9B4fDD0B094d5864fac56313f5e665", + "contractAddress": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "transactionIndex": 10, + "gasUsed": "3488833", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000020000000000000000000000000000000000000001000000000000000000000000000000000000000000040000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000000000000000000000000000", + "blockHash": "0x332275ddebfb9d22a312b8d17d7695b1eff66ce11bcc1caf0c0dcdefb69ee6e4", + "transactionHash": "0x1863cf5ef646c0917370950b629317c013012d8f4da7ceeb4958f081af3c4487", + "logs": [ + { + "transactionIndex": 10, + "blockNumber": 12285426, + "transactionHash": "0x1863cf5ef646c0917370950b629317c013012d8f4da7ceeb4958f081af3c4487", + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000282607716d9b4fdd0b094d5864fac56313f5e665" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0x332275ddebfb9d22a312b8d17d7695b1eff66ce11bcc1caf0c0dcdefb69ee6e4" + } + ], + "blockNumber": 12285426, + "cumulativeGasUsed": "3698833", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000000", + [] + ], + "numDeployments": 1, + "solcInputHash": "e556d43a3caf4f1fb4f12d632d103b28", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bentoBox\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"priviledgedUserList\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"MinimalOutputBalanceViolation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"Route\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"algebraSwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"pancakeV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"priviledgedUsers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"priviledge\",\"type\":\"bool\"}],\"name\":\"setPriviledge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"transferValueAndprocessRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"Ilya Lyalin\",\"kind\":\"dev\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IAlgebraPoolActions#swap call\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the PancakeV3Pool#swap call\"}},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"route\":\"Route to process\",\"to\":\"Where to transfer output tokens\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IUniswapV3PoolActions#swap call\"}}},\"title\":\"A route processor for the Sushi Aggregator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\"},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Processes the route generated off-chain. Has a lock\"},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value of input tokens to and then processes the route\"},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"processes the route and sends amount of output token to \"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value to and then processes the route\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RouteProcessor5.sol\":\"RouteProcessor5\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\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 Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.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 function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\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\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\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 * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\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\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/InputStream.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\n/** @notice Simple read stream */\\nlibrary InputStream {\\n\\n /** @notice Creates stream from data\\n * @param data data\\n */\\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\\n assembly {\\n stream := mload(0x40)\\n mstore(0x40, add(stream, 64))\\n mstore(stream, data)\\n let length := mload(data)\\n mstore(add(stream, 32), add(data, length))\\n }\\n }\\n\\n /** @notice Checks if stream is not empty\\n * @param stream stream\\n */\\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\\n uint256 pos;\\n uint256 finish;\\n assembly {\\n pos := mload(stream)\\n finish := mload(add(stream, 32))\\n }\\n return pos < finish;\\n }\\n\\n /** @notice Reads uint8 from the stream\\n * @param stream stream\\n */\\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 1)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint16 from the stream\\n * @param stream stream\\n */\\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 2)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint24 from the stream\\n * @param stream stream\\n */\\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 3)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint32 from the stream\\n * @param stream stream\\n */\\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 4)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint256 from the stream\\n * @param stream stream\\n */\\n function readUint(uint256 stream) internal pure returns (uint256 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes32 from the stream\\n * @param stream stream\\n */\\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads address from the stream\\n * @param stream stream\\n */\\n function readAddress(uint256 stream) internal pure returns (address res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 20)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes from the stream\\n * @param stream stream\\n */\\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\\n assembly {\\n let pos := mload(stream)\\n res := add(pos, 32)\\n let length := mload(res)\\n mstore(stream, add(res, length))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x24e24bd0e49cbddacbf3b26bcd4bdffac63d11f3259bc05bc93c0835e8ff5300\",\"license\":\"UNLICENSED\"},\"contracts/RouteProcessor5.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '../interfaces/IUniswapV2Pair.sol';\\nimport '../interfaces/IUniswapV3Pool.sol';\\nimport '../interfaces/ITridentCLPool.sol';\\nimport '../interfaces/IBentoBoxMinimal.sol';\\nimport '../interfaces/IPool.sol';\\nimport '../interfaces/IWETH.sol';\\nimport '../interfaces/ICurve.sol';\\nimport './InputStream.sol';\\nimport './Utils.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\\n\\nuint8 constant LOCKED = 2;\\nuint8 constant NOT_LOCKED = 1;\\nuint8 constant PAUSED = 2;\\nuint8 constant NOT_PAUSED = 1;\\n\\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\nuint160 constant MIN_SQRT_RATIO = 4295128739;\\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n/// @title A route processor for the Sushi Aggregator\\n/// @author Ilya Lyalin\\ncontract RouteProcessor5 is Ownable {\\n using SafeERC20 for IERC20;\\n using Utils for IERC20;\\n using Utils for address;\\n using SafeERC20 for IERC20Permit;\\n using InputStream for uint256;\\n\\n event Route(\\n address indexed from, \\n address to, \\n address indexed tokenIn, \\n address indexed tokenOut, \\n uint256 amountIn, \\n uint256 amountOutMin,\\n uint256 amountOut\\n );\\n\\n error MinimalOutputBalanceViolation(uint256 amountOut);\\n\\n IBentoBoxMinimal public immutable bentoBox;\\n mapping (address => bool) public priviledgedUsers;\\n address private lastCalledPool;\\n\\n uint8 private unlocked = NOT_LOCKED;\\n uint8 private paused = NOT_PAUSED;\\n modifier lock() {\\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\\n unlocked = LOCKED;\\n _;\\n unlocked = NOT_LOCKED;\\n }\\n\\n modifier onlyOwnerOrPriviledgedUser() {\\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \\\"RP: caller is not the owner or a privileged user\\\");\\n _;\\n }\\n\\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\\n bentoBox = IBentoBoxMinimal(_bentoBox);\\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n\\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\\n priviledgedUsers[priviledgedUserList[i]] = true;\\n }\\n }\\n\\n function setPriviledge(address user, bool priviledge) external onlyOwner {\\n priviledgedUsers[user] = priviledge;\\n }\\n\\n function pause() external onlyOwnerOrPriviledgedUser {\\n paused = PAUSED;\\n }\\n\\n function resume() external onlyOwnerOrPriviledgedUser {\\n paused = NOT_PAUSED;\\n }\\n\\n /// @notice For native unwrapping\\n receive() external payable {}\\n\\n /// @notice Processes the route generated off-chain. Has a lock\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @param to Where to transfer output tokens\\n /// @param route Route to process\\n /// @return amountOut Actual amount of the output token\\n function processRoute(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function transferValueAndprocessRoute(\\n address transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n transferValueTo.transferNative(amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value of input tokens to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueInput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n \\n /// @notice processes the route and sends amount of output token to \\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueOutput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\\n }\\n\\n /// @notice Processes the route generated off-chain\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteInternal(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) private returns (uint256 amountOut) {\\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\\n\\n uint256 realAmountIn = amountIn;\\n {\\n uint256 step = 0;\\n uint256 stream = InputStream.createStream(route);\\n while (stream.isNotEmpty()) {\\n uint8 commandCode = stream.readUint8();\\n if (commandCode == 1) {\\n uint256 usedAmount = processMyERC20(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 2) processUserERC20(stream, amountIn);\\n else if (commandCode == 3) {\\n uint256 usedAmount = processNative(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 4) processOnePool(stream);\\n else if (commandCode == 5) processInsideBento(stream);\\n else if (commandCode == 6) applyPermit(tokenIn, stream);\\n else revert('RouteProcessor: Unknown command code');\\n ++step;\\n }\\n }\\n\\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\\n if (tokenIn != Utils.NATIVE_ADDRESS)\\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\\n \\n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\\n\\n amountOut = balanceOutFinal - balanceOutInitial;\\n\\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\\n }\\n\\n /// @notice Applies ERC-2612 permit\\n /// @param tokenIn permitted token\\n /// @param stream Streamed program\\n function applyPermit(address tokenIn, uint256 stream) private {\\n uint256 value = stream.readUint();\\n uint256 deadline = stream.readUint();\\n uint8 v = stream.readUint8();\\n bytes32 r = stream.readBytes32();\\n bytes32 s = stream.readBytes32();\\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\\n }\\n }\\n\\n /// @notice Processes native coin: call swap for all pools that swap from native coin\\n /// @param stream Streamed program\\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\\n amountTotal = address(this).balance;\\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token from this contract balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\\n address token = stream.readAddress();\\n amountTotal = IERC20(token).balanceOf(address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n \\n /// @notice Processes ERC20 token from msg.sender balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n /// @param amountTotal Amount of tokens to take from msg.sender\\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\\n address token = stream.readAddress();\\n distributeAndSwap(stream, msg.sender, token, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token for cases when the token has only one output pool\\n /// @notice In this case liquidity is already at pool balance. This is an optimization\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processOnePool(uint256 stream) private {\\n address token = stream.readAddress();\\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\\n }\\n\\n /// @notice Processes Bento tokens \\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processInsideBento(uint256 stream) private {\\n address token = stream.readAddress();\\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n\\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountTotal Total amount of tokenIn for swaps \\n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\\n uint8 num = stream.readUint8();\\n unchecked {\\n for (uint256 i = 0; i < num; ++i) {\\n uint16 share = stream.readUint16();\\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\\n amountTotal -= amount;\\n swap(stream, from, tokenIn, amount);\\n }\\n }\\n }\\n\\n /// @notice Makes swap\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 poolType = stream.readUint8();\\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\\n else revert('RouteProcessor: Unknown pool type');\\n }\\n\\n /// @notice Wraps/unwraps native token\\n /// @param stream [direction & fake, recipient, wrapToken?]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 directionAndFake = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (directionAndFake & 1 == 1) { // wrap native\\n address wrapToken = stream.readAddress();\\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\\n } else { // unwrap native\\n if (directionAndFake & 2 == 0) {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IWETH(tokenIn).withdraw(amountIn);\\n }\\n to.transferNative(amountIn);\\n }\\n }\\n\\n /// @notice Bridge/unbridge tokens to/from Bento\\n /// @param stream [direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (direction > 0) { // outside to Bento\\n // deposit to arbitrary recipient is possible only from address(bentoBox)\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\\n else {\\n // tokens already are at address(bentoBox)\\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\\n bentoBox.strategyData(tokenIn).balance -\\n bentoBox.totals(tokenIn).elastic;\\n }\\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\\n } else { // Bento to outside\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\\n }\\n }\\n\\n /// @notice UniswapV2 pool swap\\n /// @param stream [pool, direction, recipient, fee]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\\n\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\\n\\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\\n\\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\\n }\\n\\n /// @notice Trident pool swap\\n /// @param stream [pool, swapData]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bytes memory swapData = stream.readBytes();\\n\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, pool, amountIn);\\n }\\n \\n IPool(pool).swap(swapData);\\n }\\n\\n /// @notice UniswapV3 pool swap\\n /// @param stream [pool, direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bool zeroForOne = stream.readUint8() > 0;\\n address recipient = stream.readAddress();\\n\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\\n\\n lastCalledPool = pool;\\n IUniswapV3Pool(pool).swap(\\n recipient,\\n zeroForOne,\\n int256(amountIn),\\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\\n abi.encode(tokenIn)\\n );\\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) public {\\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\\n \\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n (address tokenIn) = abi.decode(data, (address));\\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\\n function algebraSwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\\n function pancakeV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 poolType = stream.readUint8();\\n int128 fromIndex = int8(stream.readUint8());\\n int128 toIndex = int8(stream.readUint8());\\n address to = stream.readAddress();\\n address tokenOut = stream.readAddress();\\n\\n uint256 amountOut;\\n if (tokenIn == Utils.NATIVE_ADDRESS) {\\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\\n } else {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IERC20(tokenIn).approveSafe(pool, amountIn);\\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n else {\\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\\n amountOut = balanceAfter - balanceBefore;\\n }\\n }\\n\\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\\n }\\n}\\n\",\"keccak256\":\"0xcd53a7f473f1847d44c42777a194203cbff02b8c761cb2935402401f57c918a2\",\"license\":\"UNLICENSED\"},\"contracts/Utils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\n\\nlibrary Utils {\\n using SafeERC20 for IERC20;\\n\\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n /**\\n * @dev returns user's balance of token (or native)\\n */\\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\\n if (token == NATIVE_ADDRESS) return address(user).balance;\\n else return IERC20(token).balanceOf(user);\\n }\\n\\n /**\\n * @dev transfers native with correct revert bubble up\\n */\\n function transferNative(address to, uint256 amount) internal {\\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\\n if (!success) {\\n assembly {\\n revert(add(32, returnBytes), mload(returnBytes))\\n }\\n }\\n }\\n\\n /**\\n * @dev transfers ERC20 or native\\n */\\n function transferAny(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\\n else IERC20(token).safeTransfer(to, amount);\\n }\\n\\n /**\\n * @dev transfers from ERC20 or transfers native\\n */\\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n (bool success, bytes memory data) = address(token).call(\\n abi.encodeWithSelector(token.approve.selector, spender, amount)\\n );\\n return success && (data.length == 0 || abi.decode(data, (bool)));\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \\n * current allowance are not zero simultaniously (USDT for example). \\n * In second case it tries to set allowance to 0, and then back to amount.\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n return approveStable(token, spender, amount) \\n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\\n }\\n}\\n\",\"keccak256\":\"0x8c8439edc00b403abd3f34be75a06b1fe71152644ae9f19488af596bbc534ffe\",\"license\":\"UNLICENSED\"},\"interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\nstruct StrategyData {\\n uint64 strategyStartDate;\\n uint64 targetPercentage;\\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n function strategyData(address token) external view returns (StrategyData memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0x0c12eba7a5b9d22d37ab8883fe22d6a312a90682809dbd11c43f8e6ceaff73bf\",\"license\":\"UNLICENSED\"},\"interfaces/ICurve.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\ninterface ICurve {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\\n}\\n\\ninterface ICurveLegacy {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\\n}\\n\\n\",\"keccak256\":\"0x3d4940b3583e06dde20f12e92d2f6ac573b3f64bdaa1e8f480656a3763852518\",\"license\":\"UNLICENSED\"},\"interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/ITridentCLPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface ITridentCLPool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bool unwrapBento,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x572376b80c86a94692b0e27e6e63790b763295e32ba1f956c1d331fc1296de8d\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IUniswapV2Pair.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Pair {\\n event Approval(address indexed owner, address indexed spender, uint value);\\n event Transfer(address indexed from, address indexed to, uint value);\\n\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function allowance(address owner, address spender) external view returns (uint);\\n\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address to, uint value) external returns (bool);\\n function transferFrom(address from, address to, uint value) external returns (bool);\\n\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n function nonces(address owner) external view returns (uint);\\n\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n event Mint(address indexed sender, uint amount0, uint amount1);\\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\\n event Swap(\\n address indexed sender,\\n uint amount0In,\\n uint amount1In,\\n uint amount0Out,\\n uint amount1Out,\\n address indexed to\\n );\\n event Sync(uint112 reserve0, uint112 reserve1);\\n\\n function MINIMUM_LIQUIDITY() external pure returns (uint);\\n function factory() external view returns (address);\\n function token0() external view returns (address);\\n function token1() external view returns (address);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\\n function price0CumulativeLast() external view returns (uint);\\n function price1CumulativeLast() external view returns (uint);\\n function kLast() external view returns (uint);\\n\\n function mint(address to) external returns (uint liquidity);\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function skim(address to) external;\\n function sync() external;\\n\\n function initialize(address, address) external;\\n}\",\"keccak256\":\"0x08f9a63b34855eec941be8d36a04424f1a1725a2c030373fcef3afeb480ca385\",\"license\":\"GPL-3.0\"},\"interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IUniswapV3Pool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x2a4d7c6120e613f0e95d4dc8c650efb9b59e3c25c64e3e5c0a379281500f0a79\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IWETH.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0xae8529ae159f784b90fdcd0629bd03bf7b68accc81edccac53357ad08406a378\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}", + "bytecode": "0x60a06040526002805461ffff60a01b191661010160a01b1790553480156200002657600080fd5b50604051620040a3380380620040a383398101604081905262000049916200016e565b6200005433620000eb565b6001600160a01b038216608052600280546001600160a01b031916600117905560005b8151811015620000e25760018060008484815181106200009b576200009b62000257565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000d9816200026d565b91505062000077565b50505062000297565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200015357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200018257600080fd5b6200018d836200013b565b602084810151919350906001600160401b0380821115620001ad57600080fd5b818601915086601f830112620001c257600080fd5b815181811115620001d757620001d762000158565b8060051b604051601f19603f83011681018181108582111715620001ff57620001ff62000158565b6040529182528482019250838101850191898311156200021e57600080fd5b938501935b82851015620002475762000237856200013b565b8452938501939285019262000223565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200029057634e487b7160e01b600052601160045260246000fd5b5060010190565b608051613da3620003006000396000818161018d01528181611798015281816127380152818161279d01528181612807015281816128cc0152818161297901528181612a5d01528181612b6401528181612c1001528181612cdf0152612df10152613da36000f3fe6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "deployedBytecode": "0x6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "devdoc": { + "author": "Ilya Lyalin", + "kind": "dev", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IAlgebraPoolActions#swap call" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the PancakeV3Pool#swap call" + } + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "route": "Route to process", + "to": "Where to transfer output tokens", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IUniswapV3PoolActions#swap call" + } + } + }, + "title": "A route processor for the Sushi Aggregator", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IAlgebraPool#swap." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via PancakeV3Pool#swap." + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "notice": "Processes the route generated off-chain. Has a lock" + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value of input tokens to and then processes the route" + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "processes the route and sends amount of output token to " + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value to and then processes the route" + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 1060, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "priviledgedUsers", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 1062, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "lastCalledPool", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 1065, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "unlocked", + "offset": 20, + "slot": "2", + "type": "t_uint8" + }, + { + "astId": 1068, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "paused", + "offset": 21, + "slot": "2", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/haqq/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json b/protocols/route-processor/deployments/haqq/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json new file mode 100644 index 0000000000..01826e7b93 --- /dev/null +++ b/protocols/route-processor/deployments/haqq/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json @@ -0,0 +1,80 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" + }, + "contracts/InputStream.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" + }, + "contracts/RouteProcessor5.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" + }, + "contracts/Utils.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "interfaces/IBentoBoxMinimal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" + }, + "interfaces/ICurve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" + }, + "interfaces/IPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" + }, + "interfaces/ITridentCLPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/harmony/RouteProcessor5.json b/protocols/route-processor/deployments/harmony/RouteProcessor5.json new file mode 100644 index 0000000000..98a763657c --- /dev/null +++ b/protocols/route-processor/deployments/harmony/RouteProcessor5.json @@ -0,0 +1,704 @@ +{ + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_bentoBox", + "type": "address" + }, + { + "internalType": "address[]", + "name": "priviledgedUserList", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "MinimalOutputBalanceViolation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Route", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "algebraSwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bentoBox", + "outputs": [ + { + "internalType": "contract IBentoBoxMinimal", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "pancakeV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "priviledgedUsers", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueInput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "priviledge", + "type": "bool" + } + ], + "name": "setPriviledge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "transferValueAndprocessRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x0467a80c92e9a81a6d69c1aa86e2b2b640e00e4b0e52559b2e423d70319197af", + "receipt": { + "to": null, + "from": "0x282607716D9B4fDD0B094d5864fac56313f5e665", + "contractAddress": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "transactionIndex": 0, + "gasUsed": "3487633", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000020000000000000000000000000000000000000001000000000000000000000000000000000000000000040000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000000000000000000000000000", + "blockHash": "0xe75380230b7d9b3c65ea2ed1d393a00bc0ce318b614dd28379c508307c6bb694", + "transactionHash": "0x0467a80c92e9a81a6d69c1aa86e2b2b640e00e4b0e52559b2e423d70319197af", + "logs": [ + { + "transactionIndex": 0, + "blockNumber": 60780520, + "transactionHash": "0x0467a80c92e9a81a6d69c1aa86e2b2b640e00e4b0e52559b2e423d70319197af", + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000282607716d9b4fdd0b094d5864fac56313f5e665" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0xe75380230b7d9b3c65ea2ed1d393a00bc0ce318b614dd28379c508307c6bb694" + } + ], + "blockNumber": 60780520, + "cumulativeGasUsed": "3487633", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000000", + [] + ], + "numDeployments": 1, + "solcInputHash": "e556d43a3caf4f1fb4f12d632d103b28", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bentoBox\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"priviledgedUserList\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"MinimalOutputBalanceViolation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"Route\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"algebraSwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"pancakeV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"priviledgedUsers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"priviledge\",\"type\":\"bool\"}],\"name\":\"setPriviledge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"transferValueAndprocessRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"Ilya Lyalin\",\"kind\":\"dev\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IAlgebraPoolActions#swap call\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the PancakeV3Pool#swap call\"}},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"route\":\"Route to process\",\"to\":\"Where to transfer output tokens\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IUniswapV3PoolActions#swap call\"}}},\"title\":\"A route processor for the Sushi Aggregator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\"},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Processes the route generated off-chain. Has a lock\"},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value of input tokens to and then processes the route\"},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"processes the route and sends amount of output token to \"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value to and then processes the route\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RouteProcessor5.sol\":\"RouteProcessor5\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\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 Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.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 function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\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\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\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 * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\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\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/InputStream.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\n/** @notice Simple read stream */\\nlibrary InputStream {\\n\\n /** @notice Creates stream from data\\n * @param data data\\n */\\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\\n assembly {\\n stream := mload(0x40)\\n mstore(0x40, add(stream, 64))\\n mstore(stream, data)\\n let length := mload(data)\\n mstore(add(stream, 32), add(data, length))\\n }\\n }\\n\\n /** @notice Checks if stream is not empty\\n * @param stream stream\\n */\\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\\n uint256 pos;\\n uint256 finish;\\n assembly {\\n pos := mload(stream)\\n finish := mload(add(stream, 32))\\n }\\n return pos < finish;\\n }\\n\\n /** @notice Reads uint8 from the stream\\n * @param stream stream\\n */\\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 1)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint16 from the stream\\n * @param stream stream\\n */\\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 2)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint24 from the stream\\n * @param stream stream\\n */\\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 3)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint32 from the stream\\n * @param stream stream\\n */\\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 4)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint256 from the stream\\n * @param stream stream\\n */\\n function readUint(uint256 stream) internal pure returns (uint256 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes32 from the stream\\n * @param stream stream\\n */\\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads address from the stream\\n * @param stream stream\\n */\\n function readAddress(uint256 stream) internal pure returns (address res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 20)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes from the stream\\n * @param stream stream\\n */\\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\\n assembly {\\n let pos := mload(stream)\\n res := add(pos, 32)\\n let length := mload(res)\\n mstore(stream, add(res, length))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x24e24bd0e49cbddacbf3b26bcd4bdffac63d11f3259bc05bc93c0835e8ff5300\",\"license\":\"UNLICENSED\"},\"contracts/RouteProcessor5.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '../interfaces/IUniswapV2Pair.sol';\\nimport '../interfaces/IUniswapV3Pool.sol';\\nimport '../interfaces/ITridentCLPool.sol';\\nimport '../interfaces/IBentoBoxMinimal.sol';\\nimport '../interfaces/IPool.sol';\\nimport '../interfaces/IWETH.sol';\\nimport '../interfaces/ICurve.sol';\\nimport './InputStream.sol';\\nimport './Utils.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\\n\\nuint8 constant LOCKED = 2;\\nuint8 constant NOT_LOCKED = 1;\\nuint8 constant PAUSED = 2;\\nuint8 constant NOT_PAUSED = 1;\\n\\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\nuint160 constant MIN_SQRT_RATIO = 4295128739;\\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n/// @title A route processor for the Sushi Aggregator\\n/// @author Ilya Lyalin\\ncontract RouteProcessor5 is Ownable {\\n using SafeERC20 for IERC20;\\n using Utils for IERC20;\\n using Utils for address;\\n using SafeERC20 for IERC20Permit;\\n using InputStream for uint256;\\n\\n event Route(\\n address indexed from, \\n address to, \\n address indexed tokenIn, \\n address indexed tokenOut, \\n uint256 amountIn, \\n uint256 amountOutMin,\\n uint256 amountOut\\n );\\n\\n error MinimalOutputBalanceViolation(uint256 amountOut);\\n\\n IBentoBoxMinimal public immutable bentoBox;\\n mapping (address => bool) public priviledgedUsers;\\n address private lastCalledPool;\\n\\n uint8 private unlocked = NOT_LOCKED;\\n uint8 private paused = NOT_PAUSED;\\n modifier lock() {\\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\\n unlocked = LOCKED;\\n _;\\n unlocked = NOT_LOCKED;\\n }\\n\\n modifier onlyOwnerOrPriviledgedUser() {\\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \\\"RP: caller is not the owner or a privileged user\\\");\\n _;\\n }\\n\\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\\n bentoBox = IBentoBoxMinimal(_bentoBox);\\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n\\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\\n priviledgedUsers[priviledgedUserList[i]] = true;\\n }\\n }\\n\\n function setPriviledge(address user, bool priviledge) external onlyOwner {\\n priviledgedUsers[user] = priviledge;\\n }\\n\\n function pause() external onlyOwnerOrPriviledgedUser {\\n paused = PAUSED;\\n }\\n\\n function resume() external onlyOwnerOrPriviledgedUser {\\n paused = NOT_PAUSED;\\n }\\n\\n /// @notice For native unwrapping\\n receive() external payable {}\\n\\n /// @notice Processes the route generated off-chain. Has a lock\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @param to Where to transfer output tokens\\n /// @param route Route to process\\n /// @return amountOut Actual amount of the output token\\n function processRoute(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function transferValueAndprocessRoute(\\n address transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n transferValueTo.transferNative(amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value of input tokens to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueInput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n \\n /// @notice processes the route and sends amount of output token to \\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueOutput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\\n }\\n\\n /// @notice Processes the route generated off-chain\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteInternal(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) private returns (uint256 amountOut) {\\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\\n\\n uint256 realAmountIn = amountIn;\\n {\\n uint256 step = 0;\\n uint256 stream = InputStream.createStream(route);\\n while (stream.isNotEmpty()) {\\n uint8 commandCode = stream.readUint8();\\n if (commandCode == 1) {\\n uint256 usedAmount = processMyERC20(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 2) processUserERC20(stream, amountIn);\\n else if (commandCode == 3) {\\n uint256 usedAmount = processNative(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 4) processOnePool(stream);\\n else if (commandCode == 5) processInsideBento(stream);\\n else if (commandCode == 6) applyPermit(tokenIn, stream);\\n else revert('RouteProcessor: Unknown command code');\\n ++step;\\n }\\n }\\n\\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\\n if (tokenIn != Utils.NATIVE_ADDRESS)\\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\\n \\n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\\n\\n amountOut = balanceOutFinal - balanceOutInitial;\\n\\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\\n }\\n\\n /// @notice Applies ERC-2612 permit\\n /// @param tokenIn permitted token\\n /// @param stream Streamed program\\n function applyPermit(address tokenIn, uint256 stream) private {\\n uint256 value = stream.readUint();\\n uint256 deadline = stream.readUint();\\n uint8 v = stream.readUint8();\\n bytes32 r = stream.readBytes32();\\n bytes32 s = stream.readBytes32();\\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\\n }\\n }\\n\\n /// @notice Processes native coin: call swap for all pools that swap from native coin\\n /// @param stream Streamed program\\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\\n amountTotal = address(this).balance;\\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token from this contract balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\\n address token = stream.readAddress();\\n amountTotal = IERC20(token).balanceOf(address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n \\n /// @notice Processes ERC20 token from msg.sender balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n /// @param amountTotal Amount of tokens to take from msg.sender\\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\\n address token = stream.readAddress();\\n distributeAndSwap(stream, msg.sender, token, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token for cases when the token has only one output pool\\n /// @notice In this case liquidity is already at pool balance. This is an optimization\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processOnePool(uint256 stream) private {\\n address token = stream.readAddress();\\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\\n }\\n\\n /// @notice Processes Bento tokens \\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processInsideBento(uint256 stream) private {\\n address token = stream.readAddress();\\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n\\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountTotal Total amount of tokenIn for swaps \\n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\\n uint8 num = stream.readUint8();\\n unchecked {\\n for (uint256 i = 0; i < num; ++i) {\\n uint16 share = stream.readUint16();\\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\\n amountTotal -= amount;\\n swap(stream, from, tokenIn, amount);\\n }\\n }\\n }\\n\\n /// @notice Makes swap\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 poolType = stream.readUint8();\\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\\n else revert('RouteProcessor: Unknown pool type');\\n }\\n\\n /// @notice Wraps/unwraps native token\\n /// @param stream [direction & fake, recipient, wrapToken?]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 directionAndFake = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (directionAndFake & 1 == 1) { // wrap native\\n address wrapToken = stream.readAddress();\\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\\n } else { // unwrap native\\n if (directionAndFake & 2 == 0) {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IWETH(tokenIn).withdraw(amountIn);\\n }\\n to.transferNative(amountIn);\\n }\\n }\\n\\n /// @notice Bridge/unbridge tokens to/from Bento\\n /// @param stream [direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (direction > 0) { // outside to Bento\\n // deposit to arbitrary recipient is possible only from address(bentoBox)\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\\n else {\\n // tokens already are at address(bentoBox)\\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\\n bentoBox.strategyData(tokenIn).balance -\\n bentoBox.totals(tokenIn).elastic;\\n }\\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\\n } else { // Bento to outside\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\\n }\\n }\\n\\n /// @notice UniswapV2 pool swap\\n /// @param stream [pool, direction, recipient, fee]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\\n\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\\n\\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\\n\\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\\n }\\n\\n /// @notice Trident pool swap\\n /// @param stream [pool, swapData]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bytes memory swapData = stream.readBytes();\\n\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, pool, amountIn);\\n }\\n \\n IPool(pool).swap(swapData);\\n }\\n\\n /// @notice UniswapV3 pool swap\\n /// @param stream [pool, direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bool zeroForOne = stream.readUint8() > 0;\\n address recipient = stream.readAddress();\\n\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\\n\\n lastCalledPool = pool;\\n IUniswapV3Pool(pool).swap(\\n recipient,\\n zeroForOne,\\n int256(amountIn),\\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\\n abi.encode(tokenIn)\\n );\\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) public {\\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\\n \\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n (address tokenIn) = abi.decode(data, (address));\\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\\n function algebraSwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\\n function pancakeV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 poolType = stream.readUint8();\\n int128 fromIndex = int8(stream.readUint8());\\n int128 toIndex = int8(stream.readUint8());\\n address to = stream.readAddress();\\n address tokenOut = stream.readAddress();\\n\\n uint256 amountOut;\\n if (tokenIn == Utils.NATIVE_ADDRESS) {\\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\\n } else {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IERC20(tokenIn).approveSafe(pool, amountIn);\\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n else {\\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\\n amountOut = balanceAfter - balanceBefore;\\n }\\n }\\n\\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\\n }\\n}\\n\",\"keccak256\":\"0xcd53a7f473f1847d44c42777a194203cbff02b8c761cb2935402401f57c918a2\",\"license\":\"UNLICENSED\"},\"contracts/Utils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\n\\nlibrary Utils {\\n using SafeERC20 for IERC20;\\n\\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n /**\\n * @dev returns user's balance of token (or native)\\n */\\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\\n if (token == NATIVE_ADDRESS) return address(user).balance;\\n else return IERC20(token).balanceOf(user);\\n }\\n\\n /**\\n * @dev transfers native with correct revert bubble up\\n */\\n function transferNative(address to, uint256 amount) internal {\\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\\n if (!success) {\\n assembly {\\n revert(add(32, returnBytes), mload(returnBytes))\\n }\\n }\\n }\\n\\n /**\\n * @dev transfers ERC20 or native\\n */\\n function transferAny(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\\n else IERC20(token).safeTransfer(to, amount);\\n }\\n\\n /**\\n * @dev transfers from ERC20 or transfers native\\n */\\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n (bool success, bytes memory data) = address(token).call(\\n abi.encodeWithSelector(token.approve.selector, spender, amount)\\n );\\n return success && (data.length == 0 || abi.decode(data, (bool)));\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \\n * current allowance are not zero simultaniously (USDT for example). \\n * In second case it tries to set allowance to 0, and then back to amount.\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n return approveStable(token, spender, amount) \\n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\\n }\\n}\\n\",\"keccak256\":\"0x8c8439edc00b403abd3f34be75a06b1fe71152644ae9f19488af596bbc534ffe\",\"license\":\"UNLICENSED\"},\"interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\nstruct StrategyData {\\n uint64 strategyStartDate;\\n uint64 targetPercentage;\\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n function strategyData(address token) external view returns (StrategyData memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0x0c12eba7a5b9d22d37ab8883fe22d6a312a90682809dbd11c43f8e6ceaff73bf\",\"license\":\"UNLICENSED\"},\"interfaces/ICurve.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\ninterface ICurve {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\\n}\\n\\ninterface ICurveLegacy {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\\n}\\n\\n\",\"keccak256\":\"0x3d4940b3583e06dde20f12e92d2f6ac573b3f64bdaa1e8f480656a3763852518\",\"license\":\"UNLICENSED\"},\"interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/ITridentCLPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface ITridentCLPool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bool unwrapBento,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x572376b80c86a94692b0e27e6e63790b763295e32ba1f956c1d331fc1296de8d\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IUniswapV2Pair.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Pair {\\n event Approval(address indexed owner, address indexed spender, uint value);\\n event Transfer(address indexed from, address indexed to, uint value);\\n\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function allowance(address owner, address spender) external view returns (uint);\\n\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address to, uint value) external returns (bool);\\n function transferFrom(address from, address to, uint value) external returns (bool);\\n\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n function nonces(address owner) external view returns (uint);\\n\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n event Mint(address indexed sender, uint amount0, uint amount1);\\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\\n event Swap(\\n address indexed sender,\\n uint amount0In,\\n uint amount1In,\\n uint amount0Out,\\n uint amount1Out,\\n address indexed to\\n );\\n event Sync(uint112 reserve0, uint112 reserve1);\\n\\n function MINIMUM_LIQUIDITY() external pure returns (uint);\\n function factory() external view returns (address);\\n function token0() external view returns (address);\\n function token1() external view returns (address);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\\n function price0CumulativeLast() external view returns (uint);\\n function price1CumulativeLast() external view returns (uint);\\n function kLast() external view returns (uint);\\n\\n function mint(address to) external returns (uint liquidity);\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function skim(address to) external;\\n function sync() external;\\n\\n function initialize(address, address) external;\\n}\",\"keccak256\":\"0x08f9a63b34855eec941be8d36a04424f1a1725a2c030373fcef3afeb480ca385\",\"license\":\"GPL-3.0\"},\"interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IUniswapV3Pool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x2a4d7c6120e613f0e95d4dc8c650efb9b59e3c25c64e3e5c0a379281500f0a79\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IWETH.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0xae8529ae159f784b90fdcd0629bd03bf7b68accc81edccac53357ad08406a378\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}", + "bytecode": "0x60a06040526002805461ffff60a01b191661010160a01b1790553480156200002657600080fd5b50604051620040a3380380620040a383398101604081905262000049916200016e565b6200005433620000eb565b6001600160a01b038216608052600280546001600160a01b031916600117905560005b8151811015620000e25760018060008484815181106200009b576200009b62000257565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000d9816200026d565b91505062000077565b50505062000297565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200015357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200018257600080fd5b6200018d836200013b565b602084810151919350906001600160401b0380821115620001ad57600080fd5b818601915086601f830112620001c257600080fd5b815181811115620001d757620001d762000158565b8060051b604051601f19603f83011681018181108582111715620001ff57620001ff62000158565b6040529182528482019250838101850191898311156200021e57600080fd5b938501935b82851015620002475762000237856200013b565b8452938501939285019262000223565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200029057634e487b7160e01b600052601160045260246000fd5b5060010190565b608051613da3620003006000396000818161018d01528181611798015281816127380152818161279d01528181612807015281816128cc0152818161297901528181612a5d01528181612b6401528181612c1001528181612cdf0152612df10152613da36000f3fe6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "deployedBytecode": "0x6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "devdoc": { + "author": "Ilya Lyalin", + "kind": "dev", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IAlgebraPoolActions#swap call" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the PancakeV3Pool#swap call" + } + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "route": "Route to process", + "to": "Where to transfer output tokens", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IUniswapV3PoolActions#swap call" + } + } + }, + "title": "A route processor for the Sushi Aggregator", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IAlgebraPool#swap." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via PancakeV3Pool#swap." + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "notice": "Processes the route generated off-chain. Has a lock" + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value of input tokens to and then processes the route" + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "processes the route and sends amount of output token to " + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value to and then processes the route" + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 1060, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "priviledgedUsers", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 1062, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "lastCalledPool", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 1065, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "unlocked", + "offset": 20, + "slot": "2", + "type": "t_uint8" + }, + { + "astId": 1068, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "paused", + "offset": 21, + "slot": "2", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/harmony/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json b/protocols/route-processor/deployments/harmony/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json new file mode 100644 index 0000000000..01826e7b93 --- /dev/null +++ b/protocols/route-processor/deployments/harmony/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json @@ -0,0 +1,80 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" + }, + "contracts/InputStream.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" + }, + "contracts/RouteProcessor5.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" + }, + "contracts/Utils.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "interfaces/IBentoBoxMinimal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" + }, + "interfaces/ICurve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" + }, + "interfaces/IPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" + }, + "interfaces/ITridentCLPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/kava/RouteProcessor5.json b/protocols/route-processor/deployments/kava/RouteProcessor5.json new file mode 100644 index 0000000000..afa784ba75 --- /dev/null +++ b/protocols/route-processor/deployments/kava/RouteProcessor5.json @@ -0,0 +1,704 @@ +{ + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_bentoBox", + "type": "address" + }, + { + "internalType": "address[]", + "name": "priviledgedUserList", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "MinimalOutputBalanceViolation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Route", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "algebraSwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bentoBox", + "outputs": [ + { + "internalType": "contract IBentoBoxMinimal", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "pancakeV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "priviledgedUsers", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueInput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "priviledge", + "type": "bool" + } + ], + "name": "setPriviledge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "transferValueAndprocessRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x04eb5c33c296b18cd4ea0018c66b2924998662de121ac8bb263a6af0161d2ae7", + "receipt": { + "to": null, + "from": "0x282607716D9B4fDD0B094d5864fac56313f5e665", + "contractAddress": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "transactionIndex": 0, + "gasUsed": "3488833", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000020000000000000000000000000000000000000001000000000000000000000000000000000000000000040000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000000000000000000000000000", + "blockHash": "0xa0c83c4d9e3599719772c971d63f94a84937bb5b9ffc6602fd86905c57ff8abe", + "transactionHash": "0x04eb5c33c296b18cd4ea0018c66b2924998662de121ac8bb263a6af0161d2ae7", + "logs": [ + { + "transactionIndex": 0, + "blockNumber": 10976216, + "transactionHash": "0x04eb5c33c296b18cd4ea0018c66b2924998662de121ac8bb263a6af0161d2ae7", + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000282607716d9b4fdd0b094d5864fac56313f5e665" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0xa0c83c4d9e3599719772c971d63f94a84937bb5b9ffc6602fd86905c57ff8abe" + } + ], + "blockNumber": 10976216, + "cumulativeGasUsed": "3488833", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000000", + [] + ], + "numDeployments": 1, + "solcInputHash": "e556d43a3caf4f1fb4f12d632d103b28", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bentoBox\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"priviledgedUserList\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"MinimalOutputBalanceViolation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"Route\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"algebraSwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"pancakeV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"priviledgedUsers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"priviledge\",\"type\":\"bool\"}],\"name\":\"setPriviledge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"transferValueAndprocessRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"Ilya Lyalin\",\"kind\":\"dev\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IAlgebraPoolActions#swap call\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the PancakeV3Pool#swap call\"}},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"route\":\"Route to process\",\"to\":\"Where to transfer output tokens\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IUniswapV3PoolActions#swap call\"}}},\"title\":\"A route processor for the Sushi Aggregator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\"},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Processes the route generated off-chain. Has a lock\"},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value of input tokens to and then processes the route\"},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"processes the route and sends amount of output token to \"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value to and then processes the route\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RouteProcessor5.sol\":\"RouteProcessor5\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\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 Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.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 function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\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\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\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 * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\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\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/InputStream.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\n/** @notice Simple read stream */\\nlibrary InputStream {\\n\\n /** @notice Creates stream from data\\n * @param data data\\n */\\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\\n assembly {\\n stream := mload(0x40)\\n mstore(0x40, add(stream, 64))\\n mstore(stream, data)\\n let length := mload(data)\\n mstore(add(stream, 32), add(data, length))\\n }\\n }\\n\\n /** @notice Checks if stream is not empty\\n * @param stream stream\\n */\\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\\n uint256 pos;\\n uint256 finish;\\n assembly {\\n pos := mload(stream)\\n finish := mload(add(stream, 32))\\n }\\n return pos < finish;\\n }\\n\\n /** @notice Reads uint8 from the stream\\n * @param stream stream\\n */\\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 1)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint16 from the stream\\n * @param stream stream\\n */\\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 2)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint24 from the stream\\n * @param stream stream\\n */\\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 3)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint32 from the stream\\n * @param stream stream\\n */\\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 4)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint256 from the stream\\n * @param stream stream\\n */\\n function readUint(uint256 stream) internal pure returns (uint256 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes32 from the stream\\n * @param stream stream\\n */\\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads address from the stream\\n * @param stream stream\\n */\\n function readAddress(uint256 stream) internal pure returns (address res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 20)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes from the stream\\n * @param stream stream\\n */\\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\\n assembly {\\n let pos := mload(stream)\\n res := add(pos, 32)\\n let length := mload(res)\\n mstore(stream, add(res, length))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x24e24bd0e49cbddacbf3b26bcd4bdffac63d11f3259bc05bc93c0835e8ff5300\",\"license\":\"UNLICENSED\"},\"contracts/RouteProcessor5.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '../interfaces/IUniswapV2Pair.sol';\\nimport '../interfaces/IUniswapV3Pool.sol';\\nimport '../interfaces/ITridentCLPool.sol';\\nimport '../interfaces/IBentoBoxMinimal.sol';\\nimport '../interfaces/IPool.sol';\\nimport '../interfaces/IWETH.sol';\\nimport '../interfaces/ICurve.sol';\\nimport './InputStream.sol';\\nimport './Utils.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\\n\\nuint8 constant LOCKED = 2;\\nuint8 constant NOT_LOCKED = 1;\\nuint8 constant PAUSED = 2;\\nuint8 constant NOT_PAUSED = 1;\\n\\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\nuint160 constant MIN_SQRT_RATIO = 4295128739;\\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n/// @title A route processor for the Sushi Aggregator\\n/// @author Ilya Lyalin\\ncontract RouteProcessor5 is Ownable {\\n using SafeERC20 for IERC20;\\n using Utils for IERC20;\\n using Utils for address;\\n using SafeERC20 for IERC20Permit;\\n using InputStream for uint256;\\n\\n event Route(\\n address indexed from, \\n address to, \\n address indexed tokenIn, \\n address indexed tokenOut, \\n uint256 amountIn, \\n uint256 amountOutMin,\\n uint256 amountOut\\n );\\n\\n error MinimalOutputBalanceViolation(uint256 amountOut);\\n\\n IBentoBoxMinimal public immutable bentoBox;\\n mapping (address => bool) public priviledgedUsers;\\n address private lastCalledPool;\\n\\n uint8 private unlocked = NOT_LOCKED;\\n uint8 private paused = NOT_PAUSED;\\n modifier lock() {\\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\\n unlocked = LOCKED;\\n _;\\n unlocked = NOT_LOCKED;\\n }\\n\\n modifier onlyOwnerOrPriviledgedUser() {\\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \\\"RP: caller is not the owner or a privileged user\\\");\\n _;\\n }\\n\\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\\n bentoBox = IBentoBoxMinimal(_bentoBox);\\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n\\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\\n priviledgedUsers[priviledgedUserList[i]] = true;\\n }\\n }\\n\\n function setPriviledge(address user, bool priviledge) external onlyOwner {\\n priviledgedUsers[user] = priviledge;\\n }\\n\\n function pause() external onlyOwnerOrPriviledgedUser {\\n paused = PAUSED;\\n }\\n\\n function resume() external onlyOwnerOrPriviledgedUser {\\n paused = NOT_PAUSED;\\n }\\n\\n /// @notice For native unwrapping\\n receive() external payable {}\\n\\n /// @notice Processes the route generated off-chain. Has a lock\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @param to Where to transfer output tokens\\n /// @param route Route to process\\n /// @return amountOut Actual amount of the output token\\n function processRoute(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function transferValueAndprocessRoute(\\n address transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n transferValueTo.transferNative(amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value of input tokens to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueInput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n \\n /// @notice processes the route and sends amount of output token to \\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueOutput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\\n }\\n\\n /// @notice Processes the route generated off-chain\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteInternal(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) private returns (uint256 amountOut) {\\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\\n\\n uint256 realAmountIn = amountIn;\\n {\\n uint256 step = 0;\\n uint256 stream = InputStream.createStream(route);\\n while (stream.isNotEmpty()) {\\n uint8 commandCode = stream.readUint8();\\n if (commandCode == 1) {\\n uint256 usedAmount = processMyERC20(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 2) processUserERC20(stream, amountIn);\\n else if (commandCode == 3) {\\n uint256 usedAmount = processNative(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 4) processOnePool(stream);\\n else if (commandCode == 5) processInsideBento(stream);\\n else if (commandCode == 6) applyPermit(tokenIn, stream);\\n else revert('RouteProcessor: Unknown command code');\\n ++step;\\n }\\n }\\n\\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\\n if (tokenIn != Utils.NATIVE_ADDRESS)\\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\\n \\n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\\n\\n amountOut = balanceOutFinal - balanceOutInitial;\\n\\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\\n }\\n\\n /// @notice Applies ERC-2612 permit\\n /// @param tokenIn permitted token\\n /// @param stream Streamed program\\n function applyPermit(address tokenIn, uint256 stream) private {\\n uint256 value = stream.readUint();\\n uint256 deadline = stream.readUint();\\n uint8 v = stream.readUint8();\\n bytes32 r = stream.readBytes32();\\n bytes32 s = stream.readBytes32();\\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\\n }\\n }\\n\\n /// @notice Processes native coin: call swap for all pools that swap from native coin\\n /// @param stream Streamed program\\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\\n amountTotal = address(this).balance;\\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token from this contract balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\\n address token = stream.readAddress();\\n amountTotal = IERC20(token).balanceOf(address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n \\n /// @notice Processes ERC20 token from msg.sender balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n /// @param amountTotal Amount of tokens to take from msg.sender\\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\\n address token = stream.readAddress();\\n distributeAndSwap(stream, msg.sender, token, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token for cases when the token has only one output pool\\n /// @notice In this case liquidity is already at pool balance. This is an optimization\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processOnePool(uint256 stream) private {\\n address token = stream.readAddress();\\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\\n }\\n\\n /// @notice Processes Bento tokens \\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processInsideBento(uint256 stream) private {\\n address token = stream.readAddress();\\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n\\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountTotal Total amount of tokenIn for swaps \\n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\\n uint8 num = stream.readUint8();\\n unchecked {\\n for (uint256 i = 0; i < num; ++i) {\\n uint16 share = stream.readUint16();\\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\\n amountTotal -= amount;\\n swap(stream, from, tokenIn, amount);\\n }\\n }\\n }\\n\\n /// @notice Makes swap\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 poolType = stream.readUint8();\\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\\n else revert('RouteProcessor: Unknown pool type');\\n }\\n\\n /// @notice Wraps/unwraps native token\\n /// @param stream [direction & fake, recipient, wrapToken?]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 directionAndFake = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (directionAndFake & 1 == 1) { // wrap native\\n address wrapToken = stream.readAddress();\\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\\n } else { // unwrap native\\n if (directionAndFake & 2 == 0) {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IWETH(tokenIn).withdraw(amountIn);\\n }\\n to.transferNative(amountIn);\\n }\\n }\\n\\n /// @notice Bridge/unbridge tokens to/from Bento\\n /// @param stream [direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (direction > 0) { // outside to Bento\\n // deposit to arbitrary recipient is possible only from address(bentoBox)\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\\n else {\\n // tokens already are at address(bentoBox)\\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\\n bentoBox.strategyData(tokenIn).balance -\\n bentoBox.totals(tokenIn).elastic;\\n }\\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\\n } else { // Bento to outside\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\\n }\\n }\\n\\n /// @notice UniswapV2 pool swap\\n /// @param stream [pool, direction, recipient, fee]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\\n\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\\n\\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\\n\\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\\n }\\n\\n /// @notice Trident pool swap\\n /// @param stream [pool, swapData]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bytes memory swapData = stream.readBytes();\\n\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, pool, amountIn);\\n }\\n \\n IPool(pool).swap(swapData);\\n }\\n\\n /// @notice UniswapV3 pool swap\\n /// @param stream [pool, direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bool zeroForOne = stream.readUint8() > 0;\\n address recipient = stream.readAddress();\\n\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\\n\\n lastCalledPool = pool;\\n IUniswapV3Pool(pool).swap(\\n recipient,\\n zeroForOne,\\n int256(amountIn),\\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\\n abi.encode(tokenIn)\\n );\\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) public {\\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\\n \\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n (address tokenIn) = abi.decode(data, (address));\\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\\n function algebraSwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\\n function pancakeV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 poolType = stream.readUint8();\\n int128 fromIndex = int8(stream.readUint8());\\n int128 toIndex = int8(stream.readUint8());\\n address to = stream.readAddress();\\n address tokenOut = stream.readAddress();\\n\\n uint256 amountOut;\\n if (tokenIn == Utils.NATIVE_ADDRESS) {\\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\\n } else {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IERC20(tokenIn).approveSafe(pool, amountIn);\\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n else {\\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\\n amountOut = balanceAfter - balanceBefore;\\n }\\n }\\n\\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\\n }\\n}\\n\",\"keccak256\":\"0xcd53a7f473f1847d44c42777a194203cbff02b8c761cb2935402401f57c918a2\",\"license\":\"UNLICENSED\"},\"contracts/Utils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\n\\nlibrary Utils {\\n using SafeERC20 for IERC20;\\n\\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n /**\\n * @dev returns user's balance of token (or native)\\n */\\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\\n if (token == NATIVE_ADDRESS) return address(user).balance;\\n else return IERC20(token).balanceOf(user);\\n }\\n\\n /**\\n * @dev transfers native with correct revert bubble up\\n */\\n function transferNative(address to, uint256 amount) internal {\\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\\n if (!success) {\\n assembly {\\n revert(add(32, returnBytes), mload(returnBytes))\\n }\\n }\\n }\\n\\n /**\\n * @dev transfers ERC20 or native\\n */\\n function transferAny(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\\n else IERC20(token).safeTransfer(to, amount);\\n }\\n\\n /**\\n * @dev transfers from ERC20 or transfers native\\n */\\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n (bool success, bytes memory data) = address(token).call(\\n abi.encodeWithSelector(token.approve.selector, spender, amount)\\n );\\n return success && (data.length == 0 || abi.decode(data, (bool)));\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \\n * current allowance are not zero simultaniously (USDT for example). \\n * In second case it tries to set allowance to 0, and then back to amount.\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n return approveStable(token, spender, amount) \\n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\\n }\\n}\\n\",\"keccak256\":\"0x8c8439edc00b403abd3f34be75a06b1fe71152644ae9f19488af596bbc534ffe\",\"license\":\"UNLICENSED\"},\"interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\nstruct StrategyData {\\n uint64 strategyStartDate;\\n uint64 targetPercentage;\\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n function strategyData(address token) external view returns (StrategyData memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0x0c12eba7a5b9d22d37ab8883fe22d6a312a90682809dbd11c43f8e6ceaff73bf\",\"license\":\"UNLICENSED\"},\"interfaces/ICurve.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\ninterface ICurve {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\\n}\\n\\ninterface ICurveLegacy {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\\n}\\n\\n\",\"keccak256\":\"0x3d4940b3583e06dde20f12e92d2f6ac573b3f64bdaa1e8f480656a3763852518\",\"license\":\"UNLICENSED\"},\"interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/ITridentCLPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface ITridentCLPool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bool unwrapBento,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x572376b80c86a94692b0e27e6e63790b763295e32ba1f956c1d331fc1296de8d\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IUniswapV2Pair.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Pair {\\n event Approval(address indexed owner, address indexed spender, uint value);\\n event Transfer(address indexed from, address indexed to, uint value);\\n\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function allowance(address owner, address spender) external view returns (uint);\\n\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address to, uint value) external returns (bool);\\n function transferFrom(address from, address to, uint value) external returns (bool);\\n\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n function nonces(address owner) external view returns (uint);\\n\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n event Mint(address indexed sender, uint amount0, uint amount1);\\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\\n event Swap(\\n address indexed sender,\\n uint amount0In,\\n uint amount1In,\\n uint amount0Out,\\n uint amount1Out,\\n address indexed to\\n );\\n event Sync(uint112 reserve0, uint112 reserve1);\\n\\n function MINIMUM_LIQUIDITY() external pure returns (uint);\\n function factory() external view returns (address);\\n function token0() external view returns (address);\\n function token1() external view returns (address);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\\n function price0CumulativeLast() external view returns (uint);\\n function price1CumulativeLast() external view returns (uint);\\n function kLast() external view returns (uint);\\n\\n function mint(address to) external returns (uint liquidity);\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function skim(address to) external;\\n function sync() external;\\n\\n function initialize(address, address) external;\\n}\",\"keccak256\":\"0x08f9a63b34855eec941be8d36a04424f1a1725a2c030373fcef3afeb480ca385\",\"license\":\"GPL-3.0\"},\"interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IUniswapV3Pool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x2a4d7c6120e613f0e95d4dc8c650efb9b59e3c25c64e3e5c0a379281500f0a79\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IWETH.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0xae8529ae159f784b90fdcd0629bd03bf7b68accc81edccac53357ad08406a378\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}", + "bytecode": "0x60a06040526002805461ffff60a01b191661010160a01b1790553480156200002657600080fd5b50604051620040a3380380620040a383398101604081905262000049916200016e565b6200005433620000eb565b6001600160a01b038216608052600280546001600160a01b031916600117905560005b8151811015620000e25760018060008484815181106200009b576200009b62000257565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000d9816200026d565b91505062000077565b50505062000297565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200015357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200018257600080fd5b6200018d836200013b565b602084810151919350906001600160401b0380821115620001ad57600080fd5b818601915086601f830112620001c257600080fd5b815181811115620001d757620001d762000158565b8060051b604051601f19603f83011681018181108582111715620001ff57620001ff62000158565b6040529182528482019250838101850191898311156200021e57600080fd5b938501935b82851015620002475762000237856200013b565b8452938501939285019262000223565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200029057634e487b7160e01b600052601160045260246000fd5b5060010190565b608051613da3620003006000396000818161018d01528181611798015281816127380152818161279d01528181612807015281816128cc0152818161297901528181612a5d01528181612b6401528181612c1001528181612cdf0152612df10152613da36000f3fe6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "deployedBytecode": "0x6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "devdoc": { + "author": "Ilya Lyalin", + "kind": "dev", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IAlgebraPoolActions#swap call" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the PancakeV3Pool#swap call" + } + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "route": "Route to process", + "to": "Where to transfer output tokens", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IUniswapV3PoolActions#swap call" + } + } + }, + "title": "A route processor for the Sushi Aggregator", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IAlgebraPool#swap." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via PancakeV3Pool#swap." + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "notice": "Processes the route generated off-chain. Has a lock" + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value of input tokens to and then processes the route" + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "processes the route and sends amount of output token to " + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value to and then processes the route" + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 1060, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "priviledgedUsers", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 1062, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "lastCalledPool", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 1065, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "unlocked", + "offset": 20, + "slot": "2", + "type": "t_uint8" + }, + { + "astId": 1068, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "paused", + "offset": 21, + "slot": "2", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/kava/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json b/protocols/route-processor/deployments/kava/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json new file mode 100644 index 0000000000..01826e7b93 --- /dev/null +++ b/protocols/route-processor/deployments/kava/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json @@ -0,0 +1,80 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" + }, + "contracts/InputStream.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" + }, + "contracts/RouteProcessor5.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" + }, + "contracts/Utils.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "interfaces/IBentoBoxMinimal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" + }, + "interfaces/ICurve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" + }, + "interfaces/IPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" + }, + "interfaces/ITridentCLPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/linea/RouteProcessor5.json b/protocols/route-processor/deployments/linea/RouteProcessor5.json new file mode 100644 index 0000000000..2c7649bedd --- /dev/null +++ b/protocols/route-processor/deployments/linea/RouteProcessor5.json @@ -0,0 +1,704 @@ +{ + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_bentoBox", + "type": "address" + }, + { + "internalType": "address[]", + "name": "priviledgedUserList", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "MinimalOutputBalanceViolation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Route", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "algebraSwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bentoBox", + "outputs": [ + { + "internalType": "contract IBentoBoxMinimal", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "pancakeV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "priviledgedUsers", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueInput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "priviledge", + "type": "bool" + } + ], + "name": "setPriviledge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "transferValueAndprocessRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x0de6aa755ffda3b5f18c24acc60fddc471ef778e2f216b7c8b25be01cccf3229", + "receipt": { + "to": null, + "from": "0x282607716D9B4fDD0B094d5864fac56313f5e665", + "contractAddress": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "transactionIndex": 6, + "gasUsed": "3488833", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000020000000000000000000000000000000000000001000000000000000000000000000000000000000000040000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000000000000000000000000000", + "blockHash": "0xc7926075afca8cda3674e8066ac7bb609399be11e62d15e4d785f1d29b6fde5b", + "transactionHash": "0x0de6aa755ffda3b5f18c24acc60fddc471ef778e2f216b7c8b25be01cccf3229", + "logs": [ + { + "transactionIndex": 6, + "blockNumber": 7419955, + "transactionHash": "0x0de6aa755ffda3b5f18c24acc60fddc471ef778e2f216b7c8b25be01cccf3229", + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000282607716d9b4fdd0b094d5864fac56313f5e665" + ], + "data": "0x", + "logIndex": 13, + "blockHash": "0xc7926075afca8cda3674e8066ac7bb609399be11e62d15e4d785f1d29b6fde5b" + } + ], + "blockNumber": 7419955, + "cumulativeGasUsed": "4256406", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000000", + [] + ], + "numDeployments": 1, + "solcInputHash": "e556d43a3caf4f1fb4f12d632d103b28", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bentoBox\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"priviledgedUserList\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"MinimalOutputBalanceViolation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"Route\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"algebraSwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"pancakeV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"priviledgedUsers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"priviledge\",\"type\":\"bool\"}],\"name\":\"setPriviledge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"transferValueAndprocessRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"Ilya Lyalin\",\"kind\":\"dev\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IAlgebraPoolActions#swap call\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the PancakeV3Pool#swap call\"}},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"route\":\"Route to process\",\"to\":\"Where to transfer output tokens\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IUniswapV3PoolActions#swap call\"}}},\"title\":\"A route processor for the Sushi Aggregator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\"},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Processes the route generated off-chain. Has a lock\"},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value of input tokens to and then processes the route\"},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"processes the route and sends amount of output token to \"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value to and then processes the route\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RouteProcessor5.sol\":\"RouteProcessor5\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\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 Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.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 function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\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\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\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 * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\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\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/InputStream.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\n/** @notice Simple read stream */\\nlibrary InputStream {\\n\\n /** @notice Creates stream from data\\n * @param data data\\n */\\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\\n assembly {\\n stream := mload(0x40)\\n mstore(0x40, add(stream, 64))\\n mstore(stream, data)\\n let length := mload(data)\\n mstore(add(stream, 32), add(data, length))\\n }\\n }\\n\\n /** @notice Checks if stream is not empty\\n * @param stream stream\\n */\\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\\n uint256 pos;\\n uint256 finish;\\n assembly {\\n pos := mload(stream)\\n finish := mload(add(stream, 32))\\n }\\n return pos < finish;\\n }\\n\\n /** @notice Reads uint8 from the stream\\n * @param stream stream\\n */\\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 1)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint16 from the stream\\n * @param stream stream\\n */\\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 2)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint24 from the stream\\n * @param stream stream\\n */\\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 3)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint32 from the stream\\n * @param stream stream\\n */\\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 4)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint256 from the stream\\n * @param stream stream\\n */\\n function readUint(uint256 stream) internal pure returns (uint256 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes32 from the stream\\n * @param stream stream\\n */\\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads address from the stream\\n * @param stream stream\\n */\\n function readAddress(uint256 stream) internal pure returns (address res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 20)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes from the stream\\n * @param stream stream\\n */\\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\\n assembly {\\n let pos := mload(stream)\\n res := add(pos, 32)\\n let length := mload(res)\\n mstore(stream, add(res, length))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x24e24bd0e49cbddacbf3b26bcd4bdffac63d11f3259bc05bc93c0835e8ff5300\",\"license\":\"UNLICENSED\"},\"contracts/RouteProcessor5.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '../interfaces/IUniswapV2Pair.sol';\\nimport '../interfaces/IUniswapV3Pool.sol';\\nimport '../interfaces/ITridentCLPool.sol';\\nimport '../interfaces/IBentoBoxMinimal.sol';\\nimport '../interfaces/IPool.sol';\\nimport '../interfaces/IWETH.sol';\\nimport '../interfaces/ICurve.sol';\\nimport './InputStream.sol';\\nimport './Utils.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\\n\\nuint8 constant LOCKED = 2;\\nuint8 constant NOT_LOCKED = 1;\\nuint8 constant PAUSED = 2;\\nuint8 constant NOT_PAUSED = 1;\\n\\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\nuint160 constant MIN_SQRT_RATIO = 4295128739;\\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n/// @title A route processor for the Sushi Aggregator\\n/// @author Ilya Lyalin\\ncontract RouteProcessor5 is Ownable {\\n using SafeERC20 for IERC20;\\n using Utils for IERC20;\\n using Utils for address;\\n using SafeERC20 for IERC20Permit;\\n using InputStream for uint256;\\n\\n event Route(\\n address indexed from, \\n address to, \\n address indexed tokenIn, \\n address indexed tokenOut, \\n uint256 amountIn, \\n uint256 amountOutMin,\\n uint256 amountOut\\n );\\n\\n error MinimalOutputBalanceViolation(uint256 amountOut);\\n\\n IBentoBoxMinimal public immutable bentoBox;\\n mapping (address => bool) public priviledgedUsers;\\n address private lastCalledPool;\\n\\n uint8 private unlocked = NOT_LOCKED;\\n uint8 private paused = NOT_PAUSED;\\n modifier lock() {\\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\\n unlocked = LOCKED;\\n _;\\n unlocked = NOT_LOCKED;\\n }\\n\\n modifier onlyOwnerOrPriviledgedUser() {\\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \\\"RP: caller is not the owner or a privileged user\\\");\\n _;\\n }\\n\\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\\n bentoBox = IBentoBoxMinimal(_bentoBox);\\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n\\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\\n priviledgedUsers[priviledgedUserList[i]] = true;\\n }\\n }\\n\\n function setPriviledge(address user, bool priviledge) external onlyOwner {\\n priviledgedUsers[user] = priviledge;\\n }\\n\\n function pause() external onlyOwnerOrPriviledgedUser {\\n paused = PAUSED;\\n }\\n\\n function resume() external onlyOwnerOrPriviledgedUser {\\n paused = NOT_PAUSED;\\n }\\n\\n /// @notice For native unwrapping\\n receive() external payable {}\\n\\n /// @notice Processes the route generated off-chain. Has a lock\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @param to Where to transfer output tokens\\n /// @param route Route to process\\n /// @return amountOut Actual amount of the output token\\n function processRoute(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function transferValueAndprocessRoute(\\n address transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n transferValueTo.transferNative(amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value of input tokens to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueInput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n \\n /// @notice processes the route and sends amount of output token to \\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueOutput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\\n }\\n\\n /// @notice Processes the route generated off-chain\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteInternal(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) private returns (uint256 amountOut) {\\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\\n\\n uint256 realAmountIn = amountIn;\\n {\\n uint256 step = 0;\\n uint256 stream = InputStream.createStream(route);\\n while (stream.isNotEmpty()) {\\n uint8 commandCode = stream.readUint8();\\n if (commandCode == 1) {\\n uint256 usedAmount = processMyERC20(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 2) processUserERC20(stream, amountIn);\\n else if (commandCode == 3) {\\n uint256 usedAmount = processNative(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 4) processOnePool(stream);\\n else if (commandCode == 5) processInsideBento(stream);\\n else if (commandCode == 6) applyPermit(tokenIn, stream);\\n else revert('RouteProcessor: Unknown command code');\\n ++step;\\n }\\n }\\n\\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\\n if (tokenIn != Utils.NATIVE_ADDRESS)\\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\\n \\n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\\n\\n amountOut = balanceOutFinal - balanceOutInitial;\\n\\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\\n }\\n\\n /// @notice Applies ERC-2612 permit\\n /// @param tokenIn permitted token\\n /// @param stream Streamed program\\n function applyPermit(address tokenIn, uint256 stream) private {\\n uint256 value = stream.readUint();\\n uint256 deadline = stream.readUint();\\n uint8 v = stream.readUint8();\\n bytes32 r = stream.readBytes32();\\n bytes32 s = stream.readBytes32();\\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\\n }\\n }\\n\\n /// @notice Processes native coin: call swap for all pools that swap from native coin\\n /// @param stream Streamed program\\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\\n amountTotal = address(this).balance;\\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token from this contract balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\\n address token = stream.readAddress();\\n amountTotal = IERC20(token).balanceOf(address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n \\n /// @notice Processes ERC20 token from msg.sender balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n /// @param amountTotal Amount of tokens to take from msg.sender\\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\\n address token = stream.readAddress();\\n distributeAndSwap(stream, msg.sender, token, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token for cases when the token has only one output pool\\n /// @notice In this case liquidity is already at pool balance. This is an optimization\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processOnePool(uint256 stream) private {\\n address token = stream.readAddress();\\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\\n }\\n\\n /// @notice Processes Bento tokens \\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processInsideBento(uint256 stream) private {\\n address token = stream.readAddress();\\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n\\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountTotal Total amount of tokenIn for swaps \\n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\\n uint8 num = stream.readUint8();\\n unchecked {\\n for (uint256 i = 0; i < num; ++i) {\\n uint16 share = stream.readUint16();\\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\\n amountTotal -= amount;\\n swap(stream, from, tokenIn, amount);\\n }\\n }\\n }\\n\\n /// @notice Makes swap\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 poolType = stream.readUint8();\\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\\n else revert('RouteProcessor: Unknown pool type');\\n }\\n\\n /// @notice Wraps/unwraps native token\\n /// @param stream [direction & fake, recipient, wrapToken?]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 directionAndFake = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (directionAndFake & 1 == 1) { // wrap native\\n address wrapToken = stream.readAddress();\\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\\n } else { // unwrap native\\n if (directionAndFake & 2 == 0) {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IWETH(tokenIn).withdraw(amountIn);\\n }\\n to.transferNative(amountIn);\\n }\\n }\\n\\n /// @notice Bridge/unbridge tokens to/from Bento\\n /// @param stream [direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (direction > 0) { // outside to Bento\\n // deposit to arbitrary recipient is possible only from address(bentoBox)\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\\n else {\\n // tokens already are at address(bentoBox)\\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\\n bentoBox.strategyData(tokenIn).balance -\\n bentoBox.totals(tokenIn).elastic;\\n }\\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\\n } else { // Bento to outside\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\\n }\\n }\\n\\n /// @notice UniswapV2 pool swap\\n /// @param stream [pool, direction, recipient, fee]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\\n\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\\n\\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\\n\\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\\n }\\n\\n /// @notice Trident pool swap\\n /// @param stream [pool, swapData]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bytes memory swapData = stream.readBytes();\\n\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, pool, amountIn);\\n }\\n \\n IPool(pool).swap(swapData);\\n }\\n\\n /// @notice UniswapV3 pool swap\\n /// @param stream [pool, direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bool zeroForOne = stream.readUint8() > 0;\\n address recipient = stream.readAddress();\\n\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\\n\\n lastCalledPool = pool;\\n IUniswapV3Pool(pool).swap(\\n recipient,\\n zeroForOne,\\n int256(amountIn),\\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\\n abi.encode(tokenIn)\\n );\\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) public {\\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\\n \\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n (address tokenIn) = abi.decode(data, (address));\\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\\n function algebraSwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\\n function pancakeV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 poolType = stream.readUint8();\\n int128 fromIndex = int8(stream.readUint8());\\n int128 toIndex = int8(stream.readUint8());\\n address to = stream.readAddress();\\n address tokenOut = stream.readAddress();\\n\\n uint256 amountOut;\\n if (tokenIn == Utils.NATIVE_ADDRESS) {\\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\\n } else {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IERC20(tokenIn).approveSafe(pool, amountIn);\\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n else {\\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\\n amountOut = balanceAfter - balanceBefore;\\n }\\n }\\n\\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\\n }\\n}\\n\",\"keccak256\":\"0xcd53a7f473f1847d44c42777a194203cbff02b8c761cb2935402401f57c918a2\",\"license\":\"UNLICENSED\"},\"contracts/Utils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\n\\nlibrary Utils {\\n using SafeERC20 for IERC20;\\n\\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n /**\\n * @dev returns user's balance of token (or native)\\n */\\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\\n if (token == NATIVE_ADDRESS) return address(user).balance;\\n else return IERC20(token).balanceOf(user);\\n }\\n\\n /**\\n * @dev transfers native with correct revert bubble up\\n */\\n function transferNative(address to, uint256 amount) internal {\\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\\n if (!success) {\\n assembly {\\n revert(add(32, returnBytes), mload(returnBytes))\\n }\\n }\\n }\\n\\n /**\\n * @dev transfers ERC20 or native\\n */\\n function transferAny(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\\n else IERC20(token).safeTransfer(to, amount);\\n }\\n\\n /**\\n * @dev transfers from ERC20 or transfers native\\n */\\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n (bool success, bytes memory data) = address(token).call(\\n abi.encodeWithSelector(token.approve.selector, spender, amount)\\n );\\n return success && (data.length == 0 || abi.decode(data, (bool)));\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \\n * current allowance are not zero simultaniously (USDT for example). \\n * In second case it tries to set allowance to 0, and then back to amount.\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n return approveStable(token, spender, amount) \\n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\\n }\\n}\\n\",\"keccak256\":\"0x8c8439edc00b403abd3f34be75a06b1fe71152644ae9f19488af596bbc534ffe\",\"license\":\"UNLICENSED\"},\"interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\nstruct StrategyData {\\n uint64 strategyStartDate;\\n uint64 targetPercentage;\\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n function strategyData(address token) external view returns (StrategyData memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0x0c12eba7a5b9d22d37ab8883fe22d6a312a90682809dbd11c43f8e6ceaff73bf\",\"license\":\"UNLICENSED\"},\"interfaces/ICurve.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\ninterface ICurve {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\\n}\\n\\ninterface ICurveLegacy {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\\n}\\n\\n\",\"keccak256\":\"0x3d4940b3583e06dde20f12e92d2f6ac573b3f64bdaa1e8f480656a3763852518\",\"license\":\"UNLICENSED\"},\"interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/ITridentCLPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface ITridentCLPool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bool unwrapBento,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x572376b80c86a94692b0e27e6e63790b763295e32ba1f956c1d331fc1296de8d\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IUniswapV2Pair.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Pair {\\n event Approval(address indexed owner, address indexed spender, uint value);\\n event Transfer(address indexed from, address indexed to, uint value);\\n\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function allowance(address owner, address spender) external view returns (uint);\\n\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address to, uint value) external returns (bool);\\n function transferFrom(address from, address to, uint value) external returns (bool);\\n\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n function nonces(address owner) external view returns (uint);\\n\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n event Mint(address indexed sender, uint amount0, uint amount1);\\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\\n event Swap(\\n address indexed sender,\\n uint amount0In,\\n uint amount1In,\\n uint amount0Out,\\n uint amount1Out,\\n address indexed to\\n );\\n event Sync(uint112 reserve0, uint112 reserve1);\\n\\n function MINIMUM_LIQUIDITY() external pure returns (uint);\\n function factory() external view returns (address);\\n function token0() external view returns (address);\\n function token1() external view returns (address);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\\n function price0CumulativeLast() external view returns (uint);\\n function price1CumulativeLast() external view returns (uint);\\n function kLast() external view returns (uint);\\n\\n function mint(address to) external returns (uint liquidity);\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function skim(address to) external;\\n function sync() external;\\n\\n function initialize(address, address) external;\\n}\",\"keccak256\":\"0x08f9a63b34855eec941be8d36a04424f1a1725a2c030373fcef3afeb480ca385\",\"license\":\"GPL-3.0\"},\"interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IUniswapV3Pool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x2a4d7c6120e613f0e95d4dc8c650efb9b59e3c25c64e3e5c0a379281500f0a79\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IWETH.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0xae8529ae159f784b90fdcd0629bd03bf7b68accc81edccac53357ad08406a378\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}", + "bytecode": "0x60a06040526002805461ffff60a01b191661010160a01b1790553480156200002657600080fd5b50604051620040a3380380620040a383398101604081905262000049916200016e565b6200005433620000eb565b6001600160a01b038216608052600280546001600160a01b031916600117905560005b8151811015620000e25760018060008484815181106200009b576200009b62000257565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000d9816200026d565b91505062000077565b50505062000297565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200015357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200018257600080fd5b6200018d836200013b565b602084810151919350906001600160401b0380821115620001ad57600080fd5b818601915086601f830112620001c257600080fd5b815181811115620001d757620001d762000158565b8060051b604051601f19603f83011681018181108582111715620001ff57620001ff62000158565b6040529182528482019250838101850191898311156200021e57600080fd5b938501935b82851015620002475762000237856200013b565b8452938501939285019262000223565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200029057634e487b7160e01b600052601160045260246000fd5b5060010190565b608051613da3620003006000396000818161018d01528181611798015281816127380152818161279d01528181612807015281816128cc0152818161297901528181612a5d01528181612b6401528181612c1001528181612cdf0152612df10152613da36000f3fe6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "deployedBytecode": "0x6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "devdoc": { + "author": "Ilya Lyalin", + "kind": "dev", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IAlgebraPoolActions#swap call" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the PancakeV3Pool#swap call" + } + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "route": "Route to process", + "to": "Where to transfer output tokens", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IUniswapV3PoolActions#swap call" + } + } + }, + "title": "A route processor for the Sushi Aggregator", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IAlgebraPool#swap." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via PancakeV3Pool#swap." + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "notice": "Processes the route generated off-chain. Has a lock" + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value of input tokens to and then processes the route" + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "processes the route and sends amount of output token to " + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value to and then processes the route" + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 1060, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "priviledgedUsers", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 1062, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "lastCalledPool", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 1065, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "unlocked", + "offset": 20, + "slot": "2", + "type": "t_uint8" + }, + { + "astId": 1068, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "paused", + "offset": 21, + "slot": "2", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/linea/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json b/protocols/route-processor/deployments/linea/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json new file mode 100644 index 0000000000..01826e7b93 --- /dev/null +++ b/protocols/route-processor/deployments/linea/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json @@ -0,0 +1,80 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" + }, + "contracts/InputStream.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" + }, + "contracts/RouteProcessor5.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" + }, + "contracts/Utils.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "interfaces/IBentoBoxMinimal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" + }, + "interfaces/ICurve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" + }, + "interfaces/IPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" + }, + "interfaces/ITridentCLPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/metis/RouteProcessor5.json b/protocols/route-processor/deployments/metis/RouteProcessor5.json new file mode 100644 index 0000000000..f4f3695819 --- /dev/null +++ b/protocols/route-processor/deployments/metis/RouteProcessor5.json @@ -0,0 +1,704 @@ +{ + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_bentoBox", + "type": "address" + }, + { + "internalType": "address[]", + "name": "priviledgedUserList", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "MinimalOutputBalanceViolation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Route", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "algebraSwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bentoBox", + "outputs": [ + { + "internalType": "contract IBentoBoxMinimal", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "pancakeV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "priviledgedUsers", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueInput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "priviledge", + "type": "bool" + } + ], + "name": "setPriviledge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "transferValueAndprocessRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0xc55246386c350dc7b3ceb8f3f4938091b72dcd522f39ff2250ccade441d85a65", + "receipt": { + "to": null, + "from": "0x282607716D9B4fDD0B094d5864fac56313f5e665", + "contractAddress": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "transactionIndex": 0, + "gasUsed": "3488833", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000020000000000000000000000000000000000000001000000000000000000000000000000000000000000040000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000000000000000000000000000", + "blockHash": "0x5ff68ea477d0d77764c06b72ff3e1614242eaba2f6f4ac25b8e82b20bbf03510", + "transactionHash": "0xc55246386c350dc7b3ceb8f3f4938091b72dcd522f39ff2250ccade441d85a65", + "logs": [ + { + "transactionIndex": 0, + "blockNumber": 17862321, + "transactionHash": "0xc55246386c350dc7b3ceb8f3f4938091b72dcd522f39ff2250ccade441d85a65", + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000282607716d9b4fdd0b094d5864fac56313f5e665" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0x5ff68ea477d0d77764c06b72ff3e1614242eaba2f6f4ac25b8e82b20bbf03510" + } + ], + "blockNumber": 17862321, + "cumulativeGasUsed": "3488833", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000000", + [] + ], + "numDeployments": 1, + "solcInputHash": "e556d43a3caf4f1fb4f12d632d103b28", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bentoBox\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"priviledgedUserList\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"MinimalOutputBalanceViolation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"Route\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"algebraSwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"pancakeV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"priviledgedUsers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"priviledge\",\"type\":\"bool\"}],\"name\":\"setPriviledge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"transferValueAndprocessRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"Ilya Lyalin\",\"kind\":\"dev\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IAlgebraPoolActions#swap call\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the PancakeV3Pool#swap call\"}},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"route\":\"Route to process\",\"to\":\"Where to transfer output tokens\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IUniswapV3PoolActions#swap call\"}}},\"title\":\"A route processor for the Sushi Aggregator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\"},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Processes the route generated off-chain. Has a lock\"},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value of input tokens to and then processes the route\"},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"processes the route and sends amount of output token to \"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value to and then processes the route\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RouteProcessor5.sol\":\"RouteProcessor5\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\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 Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.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 function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\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\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\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 * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\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\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/InputStream.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\n/** @notice Simple read stream */\\nlibrary InputStream {\\n\\n /** @notice Creates stream from data\\n * @param data data\\n */\\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\\n assembly {\\n stream := mload(0x40)\\n mstore(0x40, add(stream, 64))\\n mstore(stream, data)\\n let length := mload(data)\\n mstore(add(stream, 32), add(data, length))\\n }\\n }\\n\\n /** @notice Checks if stream is not empty\\n * @param stream stream\\n */\\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\\n uint256 pos;\\n uint256 finish;\\n assembly {\\n pos := mload(stream)\\n finish := mload(add(stream, 32))\\n }\\n return pos < finish;\\n }\\n\\n /** @notice Reads uint8 from the stream\\n * @param stream stream\\n */\\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 1)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint16 from the stream\\n * @param stream stream\\n */\\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 2)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint24 from the stream\\n * @param stream stream\\n */\\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 3)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint32 from the stream\\n * @param stream stream\\n */\\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 4)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint256 from the stream\\n * @param stream stream\\n */\\n function readUint(uint256 stream) internal pure returns (uint256 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes32 from the stream\\n * @param stream stream\\n */\\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads address from the stream\\n * @param stream stream\\n */\\n function readAddress(uint256 stream) internal pure returns (address res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 20)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes from the stream\\n * @param stream stream\\n */\\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\\n assembly {\\n let pos := mload(stream)\\n res := add(pos, 32)\\n let length := mload(res)\\n mstore(stream, add(res, length))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x24e24bd0e49cbddacbf3b26bcd4bdffac63d11f3259bc05bc93c0835e8ff5300\",\"license\":\"UNLICENSED\"},\"contracts/RouteProcessor5.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '../interfaces/IUniswapV2Pair.sol';\\nimport '../interfaces/IUniswapV3Pool.sol';\\nimport '../interfaces/ITridentCLPool.sol';\\nimport '../interfaces/IBentoBoxMinimal.sol';\\nimport '../interfaces/IPool.sol';\\nimport '../interfaces/IWETH.sol';\\nimport '../interfaces/ICurve.sol';\\nimport './InputStream.sol';\\nimport './Utils.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\\n\\nuint8 constant LOCKED = 2;\\nuint8 constant NOT_LOCKED = 1;\\nuint8 constant PAUSED = 2;\\nuint8 constant NOT_PAUSED = 1;\\n\\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\nuint160 constant MIN_SQRT_RATIO = 4295128739;\\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n/// @title A route processor for the Sushi Aggregator\\n/// @author Ilya Lyalin\\ncontract RouteProcessor5 is Ownable {\\n using SafeERC20 for IERC20;\\n using Utils for IERC20;\\n using Utils for address;\\n using SafeERC20 for IERC20Permit;\\n using InputStream for uint256;\\n\\n event Route(\\n address indexed from, \\n address to, \\n address indexed tokenIn, \\n address indexed tokenOut, \\n uint256 amountIn, \\n uint256 amountOutMin,\\n uint256 amountOut\\n );\\n\\n error MinimalOutputBalanceViolation(uint256 amountOut);\\n\\n IBentoBoxMinimal public immutable bentoBox;\\n mapping (address => bool) public priviledgedUsers;\\n address private lastCalledPool;\\n\\n uint8 private unlocked = NOT_LOCKED;\\n uint8 private paused = NOT_PAUSED;\\n modifier lock() {\\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\\n unlocked = LOCKED;\\n _;\\n unlocked = NOT_LOCKED;\\n }\\n\\n modifier onlyOwnerOrPriviledgedUser() {\\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \\\"RP: caller is not the owner or a privileged user\\\");\\n _;\\n }\\n\\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\\n bentoBox = IBentoBoxMinimal(_bentoBox);\\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n\\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\\n priviledgedUsers[priviledgedUserList[i]] = true;\\n }\\n }\\n\\n function setPriviledge(address user, bool priviledge) external onlyOwner {\\n priviledgedUsers[user] = priviledge;\\n }\\n\\n function pause() external onlyOwnerOrPriviledgedUser {\\n paused = PAUSED;\\n }\\n\\n function resume() external onlyOwnerOrPriviledgedUser {\\n paused = NOT_PAUSED;\\n }\\n\\n /// @notice For native unwrapping\\n receive() external payable {}\\n\\n /// @notice Processes the route generated off-chain. Has a lock\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @param to Where to transfer output tokens\\n /// @param route Route to process\\n /// @return amountOut Actual amount of the output token\\n function processRoute(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function transferValueAndprocessRoute(\\n address transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n transferValueTo.transferNative(amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value of input tokens to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueInput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n \\n /// @notice processes the route and sends amount of output token to \\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueOutput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\\n }\\n\\n /// @notice Processes the route generated off-chain\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteInternal(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) private returns (uint256 amountOut) {\\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\\n\\n uint256 realAmountIn = amountIn;\\n {\\n uint256 step = 0;\\n uint256 stream = InputStream.createStream(route);\\n while (stream.isNotEmpty()) {\\n uint8 commandCode = stream.readUint8();\\n if (commandCode == 1) {\\n uint256 usedAmount = processMyERC20(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 2) processUserERC20(stream, amountIn);\\n else if (commandCode == 3) {\\n uint256 usedAmount = processNative(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 4) processOnePool(stream);\\n else if (commandCode == 5) processInsideBento(stream);\\n else if (commandCode == 6) applyPermit(tokenIn, stream);\\n else revert('RouteProcessor: Unknown command code');\\n ++step;\\n }\\n }\\n\\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\\n if (tokenIn != Utils.NATIVE_ADDRESS)\\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\\n \\n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\\n\\n amountOut = balanceOutFinal - balanceOutInitial;\\n\\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\\n }\\n\\n /// @notice Applies ERC-2612 permit\\n /// @param tokenIn permitted token\\n /// @param stream Streamed program\\n function applyPermit(address tokenIn, uint256 stream) private {\\n uint256 value = stream.readUint();\\n uint256 deadline = stream.readUint();\\n uint8 v = stream.readUint8();\\n bytes32 r = stream.readBytes32();\\n bytes32 s = stream.readBytes32();\\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\\n }\\n }\\n\\n /// @notice Processes native coin: call swap for all pools that swap from native coin\\n /// @param stream Streamed program\\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\\n amountTotal = address(this).balance;\\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token from this contract balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\\n address token = stream.readAddress();\\n amountTotal = IERC20(token).balanceOf(address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n \\n /// @notice Processes ERC20 token from msg.sender balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n /// @param amountTotal Amount of tokens to take from msg.sender\\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\\n address token = stream.readAddress();\\n distributeAndSwap(stream, msg.sender, token, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token for cases when the token has only one output pool\\n /// @notice In this case liquidity is already at pool balance. This is an optimization\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processOnePool(uint256 stream) private {\\n address token = stream.readAddress();\\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\\n }\\n\\n /// @notice Processes Bento tokens \\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processInsideBento(uint256 stream) private {\\n address token = stream.readAddress();\\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n\\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountTotal Total amount of tokenIn for swaps \\n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\\n uint8 num = stream.readUint8();\\n unchecked {\\n for (uint256 i = 0; i < num; ++i) {\\n uint16 share = stream.readUint16();\\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\\n amountTotal -= amount;\\n swap(stream, from, tokenIn, amount);\\n }\\n }\\n }\\n\\n /// @notice Makes swap\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 poolType = stream.readUint8();\\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\\n else revert('RouteProcessor: Unknown pool type');\\n }\\n\\n /// @notice Wraps/unwraps native token\\n /// @param stream [direction & fake, recipient, wrapToken?]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 directionAndFake = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (directionAndFake & 1 == 1) { // wrap native\\n address wrapToken = stream.readAddress();\\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\\n } else { // unwrap native\\n if (directionAndFake & 2 == 0) {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IWETH(tokenIn).withdraw(amountIn);\\n }\\n to.transferNative(amountIn);\\n }\\n }\\n\\n /// @notice Bridge/unbridge tokens to/from Bento\\n /// @param stream [direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (direction > 0) { // outside to Bento\\n // deposit to arbitrary recipient is possible only from address(bentoBox)\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\\n else {\\n // tokens already are at address(bentoBox)\\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\\n bentoBox.strategyData(tokenIn).balance -\\n bentoBox.totals(tokenIn).elastic;\\n }\\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\\n } else { // Bento to outside\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\\n }\\n }\\n\\n /// @notice UniswapV2 pool swap\\n /// @param stream [pool, direction, recipient, fee]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\\n\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\\n\\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\\n\\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\\n }\\n\\n /// @notice Trident pool swap\\n /// @param stream [pool, swapData]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bytes memory swapData = stream.readBytes();\\n\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, pool, amountIn);\\n }\\n \\n IPool(pool).swap(swapData);\\n }\\n\\n /// @notice UniswapV3 pool swap\\n /// @param stream [pool, direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bool zeroForOne = stream.readUint8() > 0;\\n address recipient = stream.readAddress();\\n\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\\n\\n lastCalledPool = pool;\\n IUniswapV3Pool(pool).swap(\\n recipient,\\n zeroForOne,\\n int256(amountIn),\\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\\n abi.encode(tokenIn)\\n );\\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) public {\\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\\n \\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n (address tokenIn) = abi.decode(data, (address));\\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\\n function algebraSwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\\n function pancakeV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 poolType = stream.readUint8();\\n int128 fromIndex = int8(stream.readUint8());\\n int128 toIndex = int8(stream.readUint8());\\n address to = stream.readAddress();\\n address tokenOut = stream.readAddress();\\n\\n uint256 amountOut;\\n if (tokenIn == Utils.NATIVE_ADDRESS) {\\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\\n } else {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IERC20(tokenIn).approveSafe(pool, amountIn);\\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n else {\\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\\n amountOut = balanceAfter - balanceBefore;\\n }\\n }\\n\\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\\n }\\n}\\n\",\"keccak256\":\"0xcd53a7f473f1847d44c42777a194203cbff02b8c761cb2935402401f57c918a2\",\"license\":\"UNLICENSED\"},\"contracts/Utils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\n\\nlibrary Utils {\\n using SafeERC20 for IERC20;\\n\\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n /**\\n * @dev returns user's balance of token (or native)\\n */\\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\\n if (token == NATIVE_ADDRESS) return address(user).balance;\\n else return IERC20(token).balanceOf(user);\\n }\\n\\n /**\\n * @dev transfers native with correct revert bubble up\\n */\\n function transferNative(address to, uint256 amount) internal {\\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\\n if (!success) {\\n assembly {\\n revert(add(32, returnBytes), mload(returnBytes))\\n }\\n }\\n }\\n\\n /**\\n * @dev transfers ERC20 or native\\n */\\n function transferAny(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\\n else IERC20(token).safeTransfer(to, amount);\\n }\\n\\n /**\\n * @dev transfers from ERC20 or transfers native\\n */\\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n (bool success, bytes memory data) = address(token).call(\\n abi.encodeWithSelector(token.approve.selector, spender, amount)\\n );\\n return success && (data.length == 0 || abi.decode(data, (bool)));\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \\n * current allowance are not zero simultaniously (USDT for example). \\n * In second case it tries to set allowance to 0, and then back to amount.\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n return approveStable(token, spender, amount) \\n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\\n }\\n}\\n\",\"keccak256\":\"0x8c8439edc00b403abd3f34be75a06b1fe71152644ae9f19488af596bbc534ffe\",\"license\":\"UNLICENSED\"},\"interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\nstruct StrategyData {\\n uint64 strategyStartDate;\\n uint64 targetPercentage;\\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n function strategyData(address token) external view returns (StrategyData memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0x0c12eba7a5b9d22d37ab8883fe22d6a312a90682809dbd11c43f8e6ceaff73bf\",\"license\":\"UNLICENSED\"},\"interfaces/ICurve.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\ninterface ICurve {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\\n}\\n\\ninterface ICurveLegacy {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\\n}\\n\\n\",\"keccak256\":\"0x3d4940b3583e06dde20f12e92d2f6ac573b3f64bdaa1e8f480656a3763852518\",\"license\":\"UNLICENSED\"},\"interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/ITridentCLPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface ITridentCLPool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bool unwrapBento,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x572376b80c86a94692b0e27e6e63790b763295e32ba1f956c1d331fc1296de8d\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IUniswapV2Pair.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Pair {\\n event Approval(address indexed owner, address indexed spender, uint value);\\n event Transfer(address indexed from, address indexed to, uint value);\\n\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function allowance(address owner, address spender) external view returns (uint);\\n\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address to, uint value) external returns (bool);\\n function transferFrom(address from, address to, uint value) external returns (bool);\\n\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n function nonces(address owner) external view returns (uint);\\n\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n event Mint(address indexed sender, uint amount0, uint amount1);\\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\\n event Swap(\\n address indexed sender,\\n uint amount0In,\\n uint amount1In,\\n uint amount0Out,\\n uint amount1Out,\\n address indexed to\\n );\\n event Sync(uint112 reserve0, uint112 reserve1);\\n\\n function MINIMUM_LIQUIDITY() external pure returns (uint);\\n function factory() external view returns (address);\\n function token0() external view returns (address);\\n function token1() external view returns (address);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\\n function price0CumulativeLast() external view returns (uint);\\n function price1CumulativeLast() external view returns (uint);\\n function kLast() external view returns (uint);\\n\\n function mint(address to) external returns (uint liquidity);\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function skim(address to) external;\\n function sync() external;\\n\\n function initialize(address, address) external;\\n}\",\"keccak256\":\"0x08f9a63b34855eec941be8d36a04424f1a1725a2c030373fcef3afeb480ca385\",\"license\":\"GPL-3.0\"},\"interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IUniswapV3Pool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x2a4d7c6120e613f0e95d4dc8c650efb9b59e3c25c64e3e5c0a379281500f0a79\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IWETH.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0xae8529ae159f784b90fdcd0629bd03bf7b68accc81edccac53357ad08406a378\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}", + "bytecode": "0x60a06040526002805461ffff60a01b191661010160a01b1790553480156200002657600080fd5b50604051620040a3380380620040a383398101604081905262000049916200016e565b6200005433620000eb565b6001600160a01b038216608052600280546001600160a01b031916600117905560005b8151811015620000e25760018060008484815181106200009b576200009b62000257565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000d9816200026d565b91505062000077565b50505062000297565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200015357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200018257600080fd5b6200018d836200013b565b602084810151919350906001600160401b0380821115620001ad57600080fd5b818601915086601f830112620001c257600080fd5b815181811115620001d757620001d762000158565b8060051b604051601f19603f83011681018181108582111715620001ff57620001ff62000158565b6040529182528482019250838101850191898311156200021e57600080fd5b938501935b82851015620002475762000237856200013b565b8452938501939285019262000223565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200029057634e487b7160e01b600052601160045260246000fd5b5060010190565b608051613da3620003006000396000818161018d01528181611798015281816127380152818161279d01528181612807015281816128cc0152818161297901528181612a5d01528181612b6401528181612c1001528181612cdf0152612df10152613da36000f3fe6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "deployedBytecode": "0x6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "devdoc": { + "author": "Ilya Lyalin", + "kind": "dev", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IAlgebraPoolActions#swap call" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the PancakeV3Pool#swap call" + } + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "route": "Route to process", + "to": "Where to transfer output tokens", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IUniswapV3PoolActions#swap call" + } + } + }, + "title": "A route processor for the Sushi Aggregator", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IAlgebraPool#swap." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via PancakeV3Pool#swap." + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "notice": "Processes the route generated off-chain. Has a lock" + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value of input tokens to and then processes the route" + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "processes the route and sends amount of output token to " + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value to and then processes the route" + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 1060, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "priviledgedUsers", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 1062, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "lastCalledPool", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 1065, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "unlocked", + "offset": 20, + "slot": "2", + "type": "t_uint8" + }, + { + "astId": 1068, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "paused", + "offset": 21, + "slot": "2", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/metis/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json b/protocols/route-processor/deployments/metis/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json new file mode 100644 index 0000000000..01826e7b93 --- /dev/null +++ b/protocols/route-processor/deployments/metis/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json @@ -0,0 +1,80 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" + }, + "contracts/InputStream.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" + }, + "contracts/RouteProcessor5.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" + }, + "contracts/Utils.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "interfaces/IBentoBoxMinimal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" + }, + "interfaces/ICurve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" + }, + "interfaces/IPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" + }, + "interfaces/ITridentCLPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/moonbeam/RouteProcessor5.json b/protocols/route-processor/deployments/moonbeam/RouteProcessor5.json new file mode 100644 index 0000000000..a56ca15dd0 --- /dev/null +++ b/protocols/route-processor/deployments/moonbeam/RouteProcessor5.json @@ -0,0 +1,704 @@ +{ + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_bentoBox", + "type": "address" + }, + { + "internalType": "address[]", + "name": "priviledgedUserList", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "MinimalOutputBalanceViolation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Route", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "algebraSwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bentoBox", + "outputs": [ + { + "internalType": "contract IBentoBoxMinimal", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "pancakeV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "priviledgedUsers", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueInput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "priviledge", + "type": "bool" + } + ], + "name": "setPriviledge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "transferValueAndprocessRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x4547c6b998f6565bcaf38d5c21acf6691f7bbfe12429a1eba2096a3fecd890b6", + "receipt": { + "to": null, + "from": "0x282607716D9B4fDD0B094d5864fac56313f5e665", + "contractAddress": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "transactionIndex": 0, + "gasUsed": "5901018", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000020000000000000000000000000000000000000001000000000000000000000000000000000000000000040000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000000000000000000000000000", + "blockHash": "0x3f5544566b7d5e7bca15f25a84e94b6d71c678ae25761bf8827f24141abd279e", + "transactionHash": "0x4547c6b998f6565bcaf38d5c21acf6691f7bbfe12429a1eba2096a3fecd890b6", + "logs": [ + { + "transactionIndex": 0, + "blockNumber": 6789446, + "transactionHash": "0x4547c6b998f6565bcaf38d5c21acf6691f7bbfe12429a1eba2096a3fecd890b6", + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000282607716d9b4fdd0b094d5864fac56313f5e665" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0x3f5544566b7d5e7bca15f25a84e94b6d71c678ae25761bf8827f24141abd279e" + } + ], + "blockNumber": 6789446, + "cumulativeGasUsed": "5901018", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000000", + [] + ], + "numDeployments": 1, + "solcInputHash": "e556d43a3caf4f1fb4f12d632d103b28", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bentoBox\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"priviledgedUserList\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"MinimalOutputBalanceViolation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"Route\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"algebraSwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"pancakeV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"priviledgedUsers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"priviledge\",\"type\":\"bool\"}],\"name\":\"setPriviledge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"transferValueAndprocessRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"Ilya Lyalin\",\"kind\":\"dev\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IAlgebraPoolActions#swap call\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the PancakeV3Pool#swap call\"}},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"route\":\"Route to process\",\"to\":\"Where to transfer output tokens\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IUniswapV3PoolActions#swap call\"}}},\"title\":\"A route processor for the Sushi Aggregator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\"},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Processes the route generated off-chain. Has a lock\"},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value of input tokens to and then processes the route\"},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"processes the route and sends amount of output token to \"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value to and then processes the route\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RouteProcessor5.sol\":\"RouteProcessor5\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\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 Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.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 function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\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\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\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 * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\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\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/InputStream.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\n/** @notice Simple read stream */\\nlibrary InputStream {\\n\\n /** @notice Creates stream from data\\n * @param data data\\n */\\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\\n assembly {\\n stream := mload(0x40)\\n mstore(0x40, add(stream, 64))\\n mstore(stream, data)\\n let length := mload(data)\\n mstore(add(stream, 32), add(data, length))\\n }\\n }\\n\\n /** @notice Checks if stream is not empty\\n * @param stream stream\\n */\\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\\n uint256 pos;\\n uint256 finish;\\n assembly {\\n pos := mload(stream)\\n finish := mload(add(stream, 32))\\n }\\n return pos < finish;\\n }\\n\\n /** @notice Reads uint8 from the stream\\n * @param stream stream\\n */\\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 1)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint16 from the stream\\n * @param stream stream\\n */\\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 2)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint24 from the stream\\n * @param stream stream\\n */\\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 3)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint32 from the stream\\n * @param stream stream\\n */\\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 4)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint256 from the stream\\n * @param stream stream\\n */\\n function readUint(uint256 stream) internal pure returns (uint256 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes32 from the stream\\n * @param stream stream\\n */\\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads address from the stream\\n * @param stream stream\\n */\\n function readAddress(uint256 stream) internal pure returns (address res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 20)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes from the stream\\n * @param stream stream\\n */\\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\\n assembly {\\n let pos := mload(stream)\\n res := add(pos, 32)\\n let length := mload(res)\\n mstore(stream, add(res, length))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x24e24bd0e49cbddacbf3b26bcd4bdffac63d11f3259bc05bc93c0835e8ff5300\",\"license\":\"UNLICENSED\"},\"contracts/RouteProcessor5.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '../interfaces/IUniswapV2Pair.sol';\\nimport '../interfaces/IUniswapV3Pool.sol';\\nimport '../interfaces/ITridentCLPool.sol';\\nimport '../interfaces/IBentoBoxMinimal.sol';\\nimport '../interfaces/IPool.sol';\\nimport '../interfaces/IWETH.sol';\\nimport '../interfaces/ICurve.sol';\\nimport './InputStream.sol';\\nimport './Utils.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\\n\\nuint8 constant LOCKED = 2;\\nuint8 constant NOT_LOCKED = 1;\\nuint8 constant PAUSED = 2;\\nuint8 constant NOT_PAUSED = 1;\\n\\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\nuint160 constant MIN_SQRT_RATIO = 4295128739;\\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n/// @title A route processor for the Sushi Aggregator\\n/// @author Ilya Lyalin\\ncontract RouteProcessor5 is Ownable {\\n using SafeERC20 for IERC20;\\n using Utils for IERC20;\\n using Utils for address;\\n using SafeERC20 for IERC20Permit;\\n using InputStream for uint256;\\n\\n event Route(\\n address indexed from, \\n address to, \\n address indexed tokenIn, \\n address indexed tokenOut, \\n uint256 amountIn, \\n uint256 amountOutMin,\\n uint256 amountOut\\n );\\n\\n error MinimalOutputBalanceViolation(uint256 amountOut);\\n\\n IBentoBoxMinimal public immutable bentoBox;\\n mapping (address => bool) public priviledgedUsers;\\n address private lastCalledPool;\\n\\n uint8 private unlocked = NOT_LOCKED;\\n uint8 private paused = NOT_PAUSED;\\n modifier lock() {\\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\\n unlocked = LOCKED;\\n _;\\n unlocked = NOT_LOCKED;\\n }\\n\\n modifier onlyOwnerOrPriviledgedUser() {\\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \\\"RP: caller is not the owner or a privileged user\\\");\\n _;\\n }\\n\\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\\n bentoBox = IBentoBoxMinimal(_bentoBox);\\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n\\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\\n priviledgedUsers[priviledgedUserList[i]] = true;\\n }\\n }\\n\\n function setPriviledge(address user, bool priviledge) external onlyOwner {\\n priviledgedUsers[user] = priviledge;\\n }\\n\\n function pause() external onlyOwnerOrPriviledgedUser {\\n paused = PAUSED;\\n }\\n\\n function resume() external onlyOwnerOrPriviledgedUser {\\n paused = NOT_PAUSED;\\n }\\n\\n /// @notice For native unwrapping\\n receive() external payable {}\\n\\n /// @notice Processes the route generated off-chain. Has a lock\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @param to Where to transfer output tokens\\n /// @param route Route to process\\n /// @return amountOut Actual amount of the output token\\n function processRoute(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function transferValueAndprocessRoute(\\n address transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n transferValueTo.transferNative(amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value of input tokens to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueInput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n \\n /// @notice processes the route and sends amount of output token to \\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueOutput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\\n }\\n\\n /// @notice Processes the route generated off-chain\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteInternal(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) private returns (uint256 amountOut) {\\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\\n\\n uint256 realAmountIn = amountIn;\\n {\\n uint256 step = 0;\\n uint256 stream = InputStream.createStream(route);\\n while (stream.isNotEmpty()) {\\n uint8 commandCode = stream.readUint8();\\n if (commandCode == 1) {\\n uint256 usedAmount = processMyERC20(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 2) processUserERC20(stream, amountIn);\\n else if (commandCode == 3) {\\n uint256 usedAmount = processNative(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 4) processOnePool(stream);\\n else if (commandCode == 5) processInsideBento(stream);\\n else if (commandCode == 6) applyPermit(tokenIn, stream);\\n else revert('RouteProcessor: Unknown command code');\\n ++step;\\n }\\n }\\n\\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\\n if (tokenIn != Utils.NATIVE_ADDRESS)\\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\\n \\n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\\n\\n amountOut = balanceOutFinal - balanceOutInitial;\\n\\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\\n }\\n\\n /// @notice Applies ERC-2612 permit\\n /// @param tokenIn permitted token\\n /// @param stream Streamed program\\n function applyPermit(address tokenIn, uint256 stream) private {\\n uint256 value = stream.readUint();\\n uint256 deadline = stream.readUint();\\n uint8 v = stream.readUint8();\\n bytes32 r = stream.readBytes32();\\n bytes32 s = stream.readBytes32();\\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\\n }\\n }\\n\\n /// @notice Processes native coin: call swap for all pools that swap from native coin\\n /// @param stream Streamed program\\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\\n amountTotal = address(this).balance;\\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token from this contract balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\\n address token = stream.readAddress();\\n amountTotal = IERC20(token).balanceOf(address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n \\n /// @notice Processes ERC20 token from msg.sender balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n /// @param amountTotal Amount of tokens to take from msg.sender\\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\\n address token = stream.readAddress();\\n distributeAndSwap(stream, msg.sender, token, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token for cases when the token has only one output pool\\n /// @notice In this case liquidity is already at pool balance. This is an optimization\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processOnePool(uint256 stream) private {\\n address token = stream.readAddress();\\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\\n }\\n\\n /// @notice Processes Bento tokens \\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processInsideBento(uint256 stream) private {\\n address token = stream.readAddress();\\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n\\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountTotal Total amount of tokenIn for swaps \\n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\\n uint8 num = stream.readUint8();\\n unchecked {\\n for (uint256 i = 0; i < num; ++i) {\\n uint16 share = stream.readUint16();\\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\\n amountTotal -= amount;\\n swap(stream, from, tokenIn, amount);\\n }\\n }\\n }\\n\\n /// @notice Makes swap\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 poolType = stream.readUint8();\\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\\n else revert('RouteProcessor: Unknown pool type');\\n }\\n\\n /// @notice Wraps/unwraps native token\\n /// @param stream [direction & fake, recipient, wrapToken?]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 directionAndFake = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (directionAndFake & 1 == 1) { // wrap native\\n address wrapToken = stream.readAddress();\\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\\n } else { // unwrap native\\n if (directionAndFake & 2 == 0) {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IWETH(tokenIn).withdraw(amountIn);\\n }\\n to.transferNative(amountIn);\\n }\\n }\\n\\n /// @notice Bridge/unbridge tokens to/from Bento\\n /// @param stream [direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (direction > 0) { // outside to Bento\\n // deposit to arbitrary recipient is possible only from address(bentoBox)\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\\n else {\\n // tokens already are at address(bentoBox)\\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\\n bentoBox.strategyData(tokenIn).balance -\\n bentoBox.totals(tokenIn).elastic;\\n }\\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\\n } else { // Bento to outside\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\\n }\\n }\\n\\n /// @notice UniswapV2 pool swap\\n /// @param stream [pool, direction, recipient, fee]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\\n\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\\n\\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\\n\\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\\n }\\n\\n /// @notice Trident pool swap\\n /// @param stream [pool, swapData]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bytes memory swapData = stream.readBytes();\\n\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, pool, amountIn);\\n }\\n \\n IPool(pool).swap(swapData);\\n }\\n\\n /// @notice UniswapV3 pool swap\\n /// @param stream [pool, direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bool zeroForOne = stream.readUint8() > 0;\\n address recipient = stream.readAddress();\\n\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\\n\\n lastCalledPool = pool;\\n IUniswapV3Pool(pool).swap(\\n recipient,\\n zeroForOne,\\n int256(amountIn),\\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\\n abi.encode(tokenIn)\\n );\\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) public {\\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\\n \\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n (address tokenIn) = abi.decode(data, (address));\\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\\n function algebraSwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\\n function pancakeV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 poolType = stream.readUint8();\\n int128 fromIndex = int8(stream.readUint8());\\n int128 toIndex = int8(stream.readUint8());\\n address to = stream.readAddress();\\n address tokenOut = stream.readAddress();\\n\\n uint256 amountOut;\\n if (tokenIn == Utils.NATIVE_ADDRESS) {\\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\\n } else {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IERC20(tokenIn).approveSafe(pool, amountIn);\\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n else {\\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\\n amountOut = balanceAfter - balanceBefore;\\n }\\n }\\n\\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\\n }\\n}\\n\",\"keccak256\":\"0xcd53a7f473f1847d44c42777a194203cbff02b8c761cb2935402401f57c918a2\",\"license\":\"UNLICENSED\"},\"contracts/Utils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\n\\nlibrary Utils {\\n using SafeERC20 for IERC20;\\n\\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n /**\\n * @dev returns user's balance of token (or native)\\n */\\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\\n if (token == NATIVE_ADDRESS) return address(user).balance;\\n else return IERC20(token).balanceOf(user);\\n }\\n\\n /**\\n * @dev transfers native with correct revert bubble up\\n */\\n function transferNative(address to, uint256 amount) internal {\\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\\n if (!success) {\\n assembly {\\n revert(add(32, returnBytes), mload(returnBytes))\\n }\\n }\\n }\\n\\n /**\\n * @dev transfers ERC20 or native\\n */\\n function transferAny(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\\n else IERC20(token).safeTransfer(to, amount);\\n }\\n\\n /**\\n * @dev transfers from ERC20 or transfers native\\n */\\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n (bool success, bytes memory data) = address(token).call(\\n abi.encodeWithSelector(token.approve.selector, spender, amount)\\n );\\n return success && (data.length == 0 || abi.decode(data, (bool)));\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \\n * current allowance are not zero simultaniously (USDT for example). \\n * In second case it tries to set allowance to 0, and then back to amount.\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n return approveStable(token, spender, amount) \\n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\\n }\\n}\\n\",\"keccak256\":\"0x8c8439edc00b403abd3f34be75a06b1fe71152644ae9f19488af596bbc534ffe\",\"license\":\"UNLICENSED\"},\"interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\nstruct StrategyData {\\n uint64 strategyStartDate;\\n uint64 targetPercentage;\\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n function strategyData(address token) external view returns (StrategyData memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0x0c12eba7a5b9d22d37ab8883fe22d6a312a90682809dbd11c43f8e6ceaff73bf\",\"license\":\"UNLICENSED\"},\"interfaces/ICurve.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\ninterface ICurve {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\\n}\\n\\ninterface ICurveLegacy {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\\n}\\n\\n\",\"keccak256\":\"0x3d4940b3583e06dde20f12e92d2f6ac573b3f64bdaa1e8f480656a3763852518\",\"license\":\"UNLICENSED\"},\"interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/ITridentCLPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface ITridentCLPool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bool unwrapBento,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x572376b80c86a94692b0e27e6e63790b763295e32ba1f956c1d331fc1296de8d\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IUniswapV2Pair.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Pair {\\n event Approval(address indexed owner, address indexed spender, uint value);\\n event Transfer(address indexed from, address indexed to, uint value);\\n\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function allowance(address owner, address spender) external view returns (uint);\\n\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address to, uint value) external returns (bool);\\n function transferFrom(address from, address to, uint value) external returns (bool);\\n\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n function nonces(address owner) external view returns (uint);\\n\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n event Mint(address indexed sender, uint amount0, uint amount1);\\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\\n event Swap(\\n address indexed sender,\\n uint amount0In,\\n uint amount1In,\\n uint amount0Out,\\n uint amount1Out,\\n address indexed to\\n );\\n event Sync(uint112 reserve0, uint112 reserve1);\\n\\n function MINIMUM_LIQUIDITY() external pure returns (uint);\\n function factory() external view returns (address);\\n function token0() external view returns (address);\\n function token1() external view returns (address);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\\n function price0CumulativeLast() external view returns (uint);\\n function price1CumulativeLast() external view returns (uint);\\n function kLast() external view returns (uint);\\n\\n function mint(address to) external returns (uint liquidity);\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function skim(address to) external;\\n function sync() external;\\n\\n function initialize(address, address) external;\\n}\",\"keccak256\":\"0x08f9a63b34855eec941be8d36a04424f1a1725a2c030373fcef3afeb480ca385\",\"license\":\"GPL-3.0\"},\"interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IUniswapV3Pool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x2a4d7c6120e613f0e95d4dc8c650efb9b59e3c25c64e3e5c0a379281500f0a79\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IWETH.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0xae8529ae159f784b90fdcd0629bd03bf7b68accc81edccac53357ad08406a378\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}", + "bytecode": "0x60a06040526002805461ffff60a01b191661010160a01b1790553480156200002657600080fd5b50604051620040a3380380620040a383398101604081905262000049916200016e565b6200005433620000eb565b6001600160a01b038216608052600280546001600160a01b031916600117905560005b8151811015620000e25760018060008484815181106200009b576200009b62000257565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000d9816200026d565b91505062000077565b50505062000297565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200015357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200018257600080fd5b6200018d836200013b565b602084810151919350906001600160401b0380821115620001ad57600080fd5b818601915086601f830112620001c257600080fd5b815181811115620001d757620001d762000158565b8060051b604051601f19603f83011681018181108582111715620001ff57620001ff62000158565b6040529182528482019250838101850191898311156200021e57600080fd5b938501935b82851015620002475762000237856200013b565b8452938501939285019262000223565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200029057634e487b7160e01b600052601160045260246000fd5b5060010190565b608051613da3620003006000396000818161018d01528181611798015281816127380152818161279d01528181612807015281816128cc0152818161297901528181612a5d01528181612b6401528181612c1001528181612cdf0152612df10152613da36000f3fe6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "deployedBytecode": "0x6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "devdoc": { + "author": "Ilya Lyalin", + "kind": "dev", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IAlgebraPoolActions#swap call" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the PancakeV3Pool#swap call" + } + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "route": "Route to process", + "to": "Where to transfer output tokens", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IUniswapV3PoolActions#swap call" + } + } + }, + "title": "A route processor for the Sushi Aggregator", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IAlgebraPool#swap." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via PancakeV3Pool#swap." + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "notice": "Processes the route generated off-chain. Has a lock" + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value of input tokens to and then processes the route" + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "processes the route and sends amount of output token to " + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value to and then processes the route" + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 1060, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "priviledgedUsers", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 1062, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "lastCalledPool", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 1065, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "unlocked", + "offset": 20, + "slot": "2", + "type": "t_uint8" + }, + { + "astId": 1068, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "paused", + "offset": 21, + "slot": "2", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/moonbeam/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json b/protocols/route-processor/deployments/moonbeam/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json new file mode 100644 index 0000000000..01826e7b93 --- /dev/null +++ b/protocols/route-processor/deployments/moonbeam/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json @@ -0,0 +1,80 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" + }, + "contracts/InputStream.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" + }, + "contracts/RouteProcessor5.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" + }, + "contracts/Utils.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "interfaces/IBentoBoxMinimal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" + }, + "interfaces/ICurve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" + }, + "interfaces/IPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" + }, + "interfaces/ITridentCLPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/moonriver/RouteProcessor5.json b/protocols/route-processor/deployments/moonriver/RouteProcessor5.json new file mode 100644 index 0000000000..0bde24ca14 --- /dev/null +++ b/protocols/route-processor/deployments/moonriver/RouteProcessor5.json @@ -0,0 +1,704 @@ +{ + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_bentoBox", + "type": "address" + }, + { + "internalType": "address[]", + "name": "priviledgedUserList", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "MinimalOutputBalanceViolation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Route", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "algebraSwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bentoBox", + "outputs": [ + { + "internalType": "contract IBentoBoxMinimal", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "pancakeV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "priviledgedUsers", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueInput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "priviledge", + "type": "bool" + } + ], + "name": "setPriviledge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "transferValueAndprocessRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x79ec1a2eb3af4d8cdb351f1a28d1149426c309011690f795ad4ecea833720636", + "receipt": { + "to": null, + "from": "0x282607716D9B4fDD0B094d5864fac56313f5e665", + "contractAddress": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "transactionIndex": 0, + "gasUsed": "5901018", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000020000000000000000000000000000000000000001000000000000000000000000000000000000000000040000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000000000000000000000000000", + "blockHash": "0x0d8c981306135fe5b8347fb57b433ff973bdb8dcb7e5cb37c9de6a35543655e0", + "transactionHash": "0x79ec1a2eb3af4d8cdb351f1a28d1149426c309011690f795ad4ecea833720636", + "logs": [ + { + "transactionIndex": 0, + "blockNumber": 7533623, + "transactionHash": "0x79ec1a2eb3af4d8cdb351f1a28d1149426c309011690f795ad4ecea833720636", + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000282607716d9b4fdd0b094d5864fac56313f5e665" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0x0d8c981306135fe5b8347fb57b433ff973bdb8dcb7e5cb37c9de6a35543655e0" + } + ], + "blockNumber": 7533623, + "cumulativeGasUsed": "5901018", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000000", + [] + ], + "numDeployments": 1, + "solcInputHash": "e556d43a3caf4f1fb4f12d632d103b28", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bentoBox\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"priviledgedUserList\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"MinimalOutputBalanceViolation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"Route\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"algebraSwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"pancakeV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"priviledgedUsers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"priviledge\",\"type\":\"bool\"}],\"name\":\"setPriviledge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"transferValueAndprocessRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"Ilya Lyalin\",\"kind\":\"dev\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IAlgebraPoolActions#swap call\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the PancakeV3Pool#swap call\"}},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"route\":\"Route to process\",\"to\":\"Where to transfer output tokens\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IUniswapV3PoolActions#swap call\"}}},\"title\":\"A route processor for the Sushi Aggregator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\"},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Processes the route generated off-chain. Has a lock\"},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value of input tokens to and then processes the route\"},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"processes the route and sends amount of output token to \"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value to and then processes the route\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RouteProcessor5.sol\":\"RouteProcessor5\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\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 Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.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 function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\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\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\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 * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\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\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/InputStream.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\n/** @notice Simple read stream */\\nlibrary InputStream {\\n\\n /** @notice Creates stream from data\\n * @param data data\\n */\\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\\n assembly {\\n stream := mload(0x40)\\n mstore(0x40, add(stream, 64))\\n mstore(stream, data)\\n let length := mload(data)\\n mstore(add(stream, 32), add(data, length))\\n }\\n }\\n\\n /** @notice Checks if stream is not empty\\n * @param stream stream\\n */\\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\\n uint256 pos;\\n uint256 finish;\\n assembly {\\n pos := mload(stream)\\n finish := mload(add(stream, 32))\\n }\\n return pos < finish;\\n }\\n\\n /** @notice Reads uint8 from the stream\\n * @param stream stream\\n */\\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 1)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint16 from the stream\\n * @param stream stream\\n */\\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 2)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint24 from the stream\\n * @param stream stream\\n */\\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 3)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint32 from the stream\\n * @param stream stream\\n */\\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 4)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint256 from the stream\\n * @param stream stream\\n */\\n function readUint(uint256 stream) internal pure returns (uint256 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes32 from the stream\\n * @param stream stream\\n */\\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads address from the stream\\n * @param stream stream\\n */\\n function readAddress(uint256 stream) internal pure returns (address res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 20)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes from the stream\\n * @param stream stream\\n */\\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\\n assembly {\\n let pos := mload(stream)\\n res := add(pos, 32)\\n let length := mload(res)\\n mstore(stream, add(res, length))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x24e24bd0e49cbddacbf3b26bcd4bdffac63d11f3259bc05bc93c0835e8ff5300\",\"license\":\"UNLICENSED\"},\"contracts/RouteProcessor5.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '../interfaces/IUniswapV2Pair.sol';\\nimport '../interfaces/IUniswapV3Pool.sol';\\nimport '../interfaces/ITridentCLPool.sol';\\nimport '../interfaces/IBentoBoxMinimal.sol';\\nimport '../interfaces/IPool.sol';\\nimport '../interfaces/IWETH.sol';\\nimport '../interfaces/ICurve.sol';\\nimport './InputStream.sol';\\nimport './Utils.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\\n\\nuint8 constant LOCKED = 2;\\nuint8 constant NOT_LOCKED = 1;\\nuint8 constant PAUSED = 2;\\nuint8 constant NOT_PAUSED = 1;\\n\\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\nuint160 constant MIN_SQRT_RATIO = 4295128739;\\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n/// @title A route processor for the Sushi Aggregator\\n/// @author Ilya Lyalin\\ncontract RouteProcessor5 is Ownable {\\n using SafeERC20 for IERC20;\\n using Utils for IERC20;\\n using Utils for address;\\n using SafeERC20 for IERC20Permit;\\n using InputStream for uint256;\\n\\n event Route(\\n address indexed from, \\n address to, \\n address indexed tokenIn, \\n address indexed tokenOut, \\n uint256 amountIn, \\n uint256 amountOutMin,\\n uint256 amountOut\\n );\\n\\n error MinimalOutputBalanceViolation(uint256 amountOut);\\n\\n IBentoBoxMinimal public immutable bentoBox;\\n mapping (address => bool) public priviledgedUsers;\\n address private lastCalledPool;\\n\\n uint8 private unlocked = NOT_LOCKED;\\n uint8 private paused = NOT_PAUSED;\\n modifier lock() {\\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\\n unlocked = LOCKED;\\n _;\\n unlocked = NOT_LOCKED;\\n }\\n\\n modifier onlyOwnerOrPriviledgedUser() {\\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \\\"RP: caller is not the owner or a privileged user\\\");\\n _;\\n }\\n\\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\\n bentoBox = IBentoBoxMinimal(_bentoBox);\\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n\\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\\n priviledgedUsers[priviledgedUserList[i]] = true;\\n }\\n }\\n\\n function setPriviledge(address user, bool priviledge) external onlyOwner {\\n priviledgedUsers[user] = priviledge;\\n }\\n\\n function pause() external onlyOwnerOrPriviledgedUser {\\n paused = PAUSED;\\n }\\n\\n function resume() external onlyOwnerOrPriviledgedUser {\\n paused = NOT_PAUSED;\\n }\\n\\n /// @notice For native unwrapping\\n receive() external payable {}\\n\\n /// @notice Processes the route generated off-chain. Has a lock\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @param to Where to transfer output tokens\\n /// @param route Route to process\\n /// @return amountOut Actual amount of the output token\\n function processRoute(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function transferValueAndprocessRoute(\\n address transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n transferValueTo.transferNative(amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value of input tokens to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueInput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n \\n /// @notice processes the route and sends amount of output token to \\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueOutput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\\n }\\n\\n /// @notice Processes the route generated off-chain\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteInternal(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) private returns (uint256 amountOut) {\\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\\n\\n uint256 realAmountIn = amountIn;\\n {\\n uint256 step = 0;\\n uint256 stream = InputStream.createStream(route);\\n while (stream.isNotEmpty()) {\\n uint8 commandCode = stream.readUint8();\\n if (commandCode == 1) {\\n uint256 usedAmount = processMyERC20(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 2) processUserERC20(stream, amountIn);\\n else if (commandCode == 3) {\\n uint256 usedAmount = processNative(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 4) processOnePool(stream);\\n else if (commandCode == 5) processInsideBento(stream);\\n else if (commandCode == 6) applyPermit(tokenIn, stream);\\n else revert('RouteProcessor: Unknown command code');\\n ++step;\\n }\\n }\\n\\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\\n if (tokenIn != Utils.NATIVE_ADDRESS)\\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\\n \\n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\\n\\n amountOut = balanceOutFinal - balanceOutInitial;\\n\\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\\n }\\n\\n /// @notice Applies ERC-2612 permit\\n /// @param tokenIn permitted token\\n /// @param stream Streamed program\\n function applyPermit(address tokenIn, uint256 stream) private {\\n uint256 value = stream.readUint();\\n uint256 deadline = stream.readUint();\\n uint8 v = stream.readUint8();\\n bytes32 r = stream.readBytes32();\\n bytes32 s = stream.readBytes32();\\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\\n }\\n }\\n\\n /// @notice Processes native coin: call swap for all pools that swap from native coin\\n /// @param stream Streamed program\\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\\n amountTotal = address(this).balance;\\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token from this contract balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\\n address token = stream.readAddress();\\n amountTotal = IERC20(token).balanceOf(address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n \\n /// @notice Processes ERC20 token from msg.sender balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n /// @param amountTotal Amount of tokens to take from msg.sender\\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\\n address token = stream.readAddress();\\n distributeAndSwap(stream, msg.sender, token, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token for cases when the token has only one output pool\\n /// @notice In this case liquidity is already at pool balance. This is an optimization\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processOnePool(uint256 stream) private {\\n address token = stream.readAddress();\\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\\n }\\n\\n /// @notice Processes Bento tokens \\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processInsideBento(uint256 stream) private {\\n address token = stream.readAddress();\\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n\\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountTotal Total amount of tokenIn for swaps \\n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\\n uint8 num = stream.readUint8();\\n unchecked {\\n for (uint256 i = 0; i < num; ++i) {\\n uint16 share = stream.readUint16();\\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\\n amountTotal -= amount;\\n swap(stream, from, tokenIn, amount);\\n }\\n }\\n }\\n\\n /// @notice Makes swap\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 poolType = stream.readUint8();\\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\\n else revert('RouteProcessor: Unknown pool type');\\n }\\n\\n /// @notice Wraps/unwraps native token\\n /// @param stream [direction & fake, recipient, wrapToken?]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 directionAndFake = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (directionAndFake & 1 == 1) { // wrap native\\n address wrapToken = stream.readAddress();\\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\\n } else { // unwrap native\\n if (directionAndFake & 2 == 0) {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IWETH(tokenIn).withdraw(amountIn);\\n }\\n to.transferNative(amountIn);\\n }\\n }\\n\\n /// @notice Bridge/unbridge tokens to/from Bento\\n /// @param stream [direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (direction > 0) { // outside to Bento\\n // deposit to arbitrary recipient is possible only from address(bentoBox)\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\\n else {\\n // tokens already are at address(bentoBox)\\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\\n bentoBox.strategyData(tokenIn).balance -\\n bentoBox.totals(tokenIn).elastic;\\n }\\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\\n } else { // Bento to outside\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\\n }\\n }\\n\\n /// @notice UniswapV2 pool swap\\n /// @param stream [pool, direction, recipient, fee]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\\n\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\\n\\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\\n\\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\\n }\\n\\n /// @notice Trident pool swap\\n /// @param stream [pool, swapData]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bytes memory swapData = stream.readBytes();\\n\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, pool, amountIn);\\n }\\n \\n IPool(pool).swap(swapData);\\n }\\n\\n /// @notice UniswapV3 pool swap\\n /// @param stream [pool, direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bool zeroForOne = stream.readUint8() > 0;\\n address recipient = stream.readAddress();\\n\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\\n\\n lastCalledPool = pool;\\n IUniswapV3Pool(pool).swap(\\n recipient,\\n zeroForOne,\\n int256(amountIn),\\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\\n abi.encode(tokenIn)\\n );\\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) public {\\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\\n \\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n (address tokenIn) = abi.decode(data, (address));\\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\\n function algebraSwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\\n function pancakeV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 poolType = stream.readUint8();\\n int128 fromIndex = int8(stream.readUint8());\\n int128 toIndex = int8(stream.readUint8());\\n address to = stream.readAddress();\\n address tokenOut = stream.readAddress();\\n\\n uint256 amountOut;\\n if (tokenIn == Utils.NATIVE_ADDRESS) {\\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\\n } else {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IERC20(tokenIn).approveSafe(pool, amountIn);\\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n else {\\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\\n amountOut = balanceAfter - balanceBefore;\\n }\\n }\\n\\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\\n }\\n}\\n\",\"keccak256\":\"0xcd53a7f473f1847d44c42777a194203cbff02b8c761cb2935402401f57c918a2\",\"license\":\"UNLICENSED\"},\"contracts/Utils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\n\\nlibrary Utils {\\n using SafeERC20 for IERC20;\\n\\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n /**\\n * @dev returns user's balance of token (or native)\\n */\\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\\n if (token == NATIVE_ADDRESS) return address(user).balance;\\n else return IERC20(token).balanceOf(user);\\n }\\n\\n /**\\n * @dev transfers native with correct revert bubble up\\n */\\n function transferNative(address to, uint256 amount) internal {\\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\\n if (!success) {\\n assembly {\\n revert(add(32, returnBytes), mload(returnBytes))\\n }\\n }\\n }\\n\\n /**\\n * @dev transfers ERC20 or native\\n */\\n function transferAny(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\\n else IERC20(token).safeTransfer(to, amount);\\n }\\n\\n /**\\n * @dev transfers from ERC20 or transfers native\\n */\\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n (bool success, bytes memory data) = address(token).call(\\n abi.encodeWithSelector(token.approve.selector, spender, amount)\\n );\\n return success && (data.length == 0 || abi.decode(data, (bool)));\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \\n * current allowance are not zero simultaniously (USDT for example). \\n * In second case it tries to set allowance to 0, and then back to amount.\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n return approveStable(token, spender, amount) \\n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\\n }\\n}\\n\",\"keccak256\":\"0x8c8439edc00b403abd3f34be75a06b1fe71152644ae9f19488af596bbc534ffe\",\"license\":\"UNLICENSED\"},\"interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\nstruct StrategyData {\\n uint64 strategyStartDate;\\n uint64 targetPercentage;\\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n function strategyData(address token) external view returns (StrategyData memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0x0c12eba7a5b9d22d37ab8883fe22d6a312a90682809dbd11c43f8e6ceaff73bf\",\"license\":\"UNLICENSED\"},\"interfaces/ICurve.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\ninterface ICurve {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\\n}\\n\\ninterface ICurveLegacy {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\\n}\\n\\n\",\"keccak256\":\"0x3d4940b3583e06dde20f12e92d2f6ac573b3f64bdaa1e8f480656a3763852518\",\"license\":\"UNLICENSED\"},\"interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/ITridentCLPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface ITridentCLPool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bool unwrapBento,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x572376b80c86a94692b0e27e6e63790b763295e32ba1f956c1d331fc1296de8d\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IUniswapV2Pair.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Pair {\\n event Approval(address indexed owner, address indexed spender, uint value);\\n event Transfer(address indexed from, address indexed to, uint value);\\n\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function allowance(address owner, address spender) external view returns (uint);\\n\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address to, uint value) external returns (bool);\\n function transferFrom(address from, address to, uint value) external returns (bool);\\n\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n function nonces(address owner) external view returns (uint);\\n\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n event Mint(address indexed sender, uint amount0, uint amount1);\\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\\n event Swap(\\n address indexed sender,\\n uint amount0In,\\n uint amount1In,\\n uint amount0Out,\\n uint amount1Out,\\n address indexed to\\n );\\n event Sync(uint112 reserve0, uint112 reserve1);\\n\\n function MINIMUM_LIQUIDITY() external pure returns (uint);\\n function factory() external view returns (address);\\n function token0() external view returns (address);\\n function token1() external view returns (address);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\\n function price0CumulativeLast() external view returns (uint);\\n function price1CumulativeLast() external view returns (uint);\\n function kLast() external view returns (uint);\\n\\n function mint(address to) external returns (uint liquidity);\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function skim(address to) external;\\n function sync() external;\\n\\n function initialize(address, address) external;\\n}\",\"keccak256\":\"0x08f9a63b34855eec941be8d36a04424f1a1725a2c030373fcef3afeb480ca385\",\"license\":\"GPL-3.0\"},\"interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IUniswapV3Pool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x2a4d7c6120e613f0e95d4dc8c650efb9b59e3c25c64e3e5c0a379281500f0a79\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IWETH.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0xae8529ae159f784b90fdcd0629bd03bf7b68accc81edccac53357ad08406a378\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}", + "bytecode": "0x60a06040526002805461ffff60a01b191661010160a01b1790553480156200002657600080fd5b50604051620040a3380380620040a383398101604081905262000049916200016e565b6200005433620000eb565b6001600160a01b038216608052600280546001600160a01b031916600117905560005b8151811015620000e25760018060008484815181106200009b576200009b62000257565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000d9816200026d565b91505062000077565b50505062000297565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200015357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200018257600080fd5b6200018d836200013b565b602084810151919350906001600160401b0380821115620001ad57600080fd5b818601915086601f830112620001c257600080fd5b815181811115620001d757620001d762000158565b8060051b604051601f19603f83011681018181108582111715620001ff57620001ff62000158565b6040529182528482019250838101850191898311156200021e57600080fd5b938501935b82851015620002475762000237856200013b565b8452938501939285019262000223565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200029057634e487b7160e01b600052601160045260246000fd5b5060010190565b608051613da3620003006000396000818161018d01528181611798015281816127380152818161279d01528181612807015281816128cc0152818161297901528181612a5d01528181612b6401528181612c1001528181612cdf0152612df10152613da36000f3fe6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "deployedBytecode": "0x6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "devdoc": { + "author": "Ilya Lyalin", + "kind": "dev", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IAlgebraPoolActions#swap call" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the PancakeV3Pool#swap call" + } + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "route": "Route to process", + "to": "Where to transfer output tokens", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IUniswapV3PoolActions#swap call" + } + } + }, + "title": "A route processor for the Sushi Aggregator", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IAlgebraPool#swap." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via PancakeV3Pool#swap." + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "notice": "Processes the route generated off-chain. Has a lock" + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value of input tokens to and then processes the route" + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "processes the route and sends amount of output token to " + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value to and then processes the route" + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 1060, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "priviledgedUsers", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 1062, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "lastCalledPool", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 1065, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "unlocked", + "offset": 20, + "slot": "2", + "type": "t_uint8" + }, + { + "astId": 1068, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "paused", + "offset": 21, + "slot": "2", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/moonriver/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json b/protocols/route-processor/deployments/moonriver/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json new file mode 100644 index 0000000000..01826e7b93 --- /dev/null +++ b/protocols/route-processor/deployments/moonriver/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json @@ -0,0 +1,80 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" + }, + "contracts/InputStream.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" + }, + "contracts/RouteProcessor5.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" + }, + "contracts/Utils.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "interfaces/IBentoBoxMinimal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" + }, + "interfaces/ICurve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" + }, + "interfaces/IPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" + }, + "interfaces/ITridentCLPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/optimism/RouteProcessor5.json b/protocols/route-processor/deployments/optimism/RouteProcessor5.json new file mode 100644 index 0000000000..08f21b359b --- /dev/null +++ b/protocols/route-processor/deployments/optimism/RouteProcessor5.json @@ -0,0 +1,704 @@ +{ + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_bentoBox", + "type": "address" + }, + { + "internalType": "address[]", + "name": "priviledgedUserList", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "MinimalOutputBalanceViolation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Route", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "algebraSwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bentoBox", + "outputs": [ + { + "internalType": "contract IBentoBoxMinimal", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "pancakeV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "priviledgedUsers", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueInput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "priviledge", + "type": "bool" + } + ], + "name": "setPriviledge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "transferValueAndprocessRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x47209c9800c27edccdb91d1491858c022700769c389d625b0773a1c55e156c62", + "receipt": { + "to": null, + "from": "0x282607716D9B4fDD0B094d5864fac56313f5e665", + "contractAddress": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "transactionIndex": 21, + "gasUsed": "3489875", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000020000000000000000000000000000000000000001000000000000000000000000000000000000000000040000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000000000000000000000000000", + "blockHash": "0xda3baa3f092ca3070c4c5a21de1317d90dfc3609518b342b0d66431ef966c282", + "transactionHash": "0x47209c9800c27edccdb91d1491858c022700769c389d625b0773a1c55e156c62", + "logs": [ + { + "transactionIndex": 21, + "blockNumber": 123318937, + "transactionHash": "0x47209c9800c27edccdb91d1491858c022700769c389d625b0773a1c55e156c62", + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000282607716d9b4fdd0b094d5864fac56313f5e665" + ], + "data": "0x", + "logIndex": 65, + "blockHash": "0xda3baa3f092ca3070c4c5a21de1317d90dfc3609518b342b0d66431ef966c282" + } + ], + "blockNumber": 123318937, + "cumulativeGasUsed": "7130212", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000000", + [] + ], + "numDeployments": 1, + "solcInputHash": "e556d43a3caf4f1fb4f12d632d103b28", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bentoBox\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"priviledgedUserList\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"MinimalOutputBalanceViolation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"Route\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"algebraSwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"pancakeV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"priviledgedUsers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"priviledge\",\"type\":\"bool\"}],\"name\":\"setPriviledge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"transferValueAndprocessRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"Ilya Lyalin\",\"kind\":\"dev\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IAlgebraPoolActions#swap call\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the PancakeV3Pool#swap call\"}},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"route\":\"Route to process\",\"to\":\"Where to transfer output tokens\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IUniswapV3PoolActions#swap call\"}}},\"title\":\"A route processor for the Sushi Aggregator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\"},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Processes the route generated off-chain. Has a lock\"},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value of input tokens to and then processes the route\"},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"processes the route and sends amount of output token to \"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value to and then processes the route\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RouteProcessor5.sol\":\"RouteProcessor5\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\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 Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.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 function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\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\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\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 * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\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\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/InputStream.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\n/** @notice Simple read stream */\\nlibrary InputStream {\\n\\n /** @notice Creates stream from data\\n * @param data data\\n */\\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\\n assembly {\\n stream := mload(0x40)\\n mstore(0x40, add(stream, 64))\\n mstore(stream, data)\\n let length := mload(data)\\n mstore(add(stream, 32), add(data, length))\\n }\\n }\\n\\n /** @notice Checks if stream is not empty\\n * @param stream stream\\n */\\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\\n uint256 pos;\\n uint256 finish;\\n assembly {\\n pos := mload(stream)\\n finish := mload(add(stream, 32))\\n }\\n return pos < finish;\\n }\\n\\n /** @notice Reads uint8 from the stream\\n * @param stream stream\\n */\\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 1)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint16 from the stream\\n * @param stream stream\\n */\\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 2)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint24 from the stream\\n * @param stream stream\\n */\\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 3)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint32 from the stream\\n * @param stream stream\\n */\\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 4)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint256 from the stream\\n * @param stream stream\\n */\\n function readUint(uint256 stream) internal pure returns (uint256 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes32 from the stream\\n * @param stream stream\\n */\\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads address from the stream\\n * @param stream stream\\n */\\n function readAddress(uint256 stream) internal pure returns (address res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 20)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes from the stream\\n * @param stream stream\\n */\\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\\n assembly {\\n let pos := mload(stream)\\n res := add(pos, 32)\\n let length := mload(res)\\n mstore(stream, add(res, length))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x24e24bd0e49cbddacbf3b26bcd4bdffac63d11f3259bc05bc93c0835e8ff5300\",\"license\":\"UNLICENSED\"},\"contracts/RouteProcessor5.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '../interfaces/IUniswapV2Pair.sol';\\nimport '../interfaces/IUniswapV3Pool.sol';\\nimport '../interfaces/ITridentCLPool.sol';\\nimport '../interfaces/IBentoBoxMinimal.sol';\\nimport '../interfaces/IPool.sol';\\nimport '../interfaces/IWETH.sol';\\nimport '../interfaces/ICurve.sol';\\nimport './InputStream.sol';\\nimport './Utils.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\\n\\nuint8 constant LOCKED = 2;\\nuint8 constant NOT_LOCKED = 1;\\nuint8 constant PAUSED = 2;\\nuint8 constant NOT_PAUSED = 1;\\n\\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\nuint160 constant MIN_SQRT_RATIO = 4295128739;\\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n/// @title A route processor for the Sushi Aggregator\\n/// @author Ilya Lyalin\\ncontract RouteProcessor5 is Ownable {\\n using SafeERC20 for IERC20;\\n using Utils for IERC20;\\n using Utils for address;\\n using SafeERC20 for IERC20Permit;\\n using InputStream for uint256;\\n\\n event Route(\\n address indexed from, \\n address to, \\n address indexed tokenIn, \\n address indexed tokenOut, \\n uint256 amountIn, \\n uint256 amountOutMin,\\n uint256 amountOut\\n );\\n\\n error MinimalOutputBalanceViolation(uint256 amountOut);\\n\\n IBentoBoxMinimal public immutable bentoBox;\\n mapping (address => bool) public priviledgedUsers;\\n address private lastCalledPool;\\n\\n uint8 private unlocked = NOT_LOCKED;\\n uint8 private paused = NOT_PAUSED;\\n modifier lock() {\\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\\n unlocked = LOCKED;\\n _;\\n unlocked = NOT_LOCKED;\\n }\\n\\n modifier onlyOwnerOrPriviledgedUser() {\\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \\\"RP: caller is not the owner or a privileged user\\\");\\n _;\\n }\\n\\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\\n bentoBox = IBentoBoxMinimal(_bentoBox);\\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n\\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\\n priviledgedUsers[priviledgedUserList[i]] = true;\\n }\\n }\\n\\n function setPriviledge(address user, bool priviledge) external onlyOwner {\\n priviledgedUsers[user] = priviledge;\\n }\\n\\n function pause() external onlyOwnerOrPriviledgedUser {\\n paused = PAUSED;\\n }\\n\\n function resume() external onlyOwnerOrPriviledgedUser {\\n paused = NOT_PAUSED;\\n }\\n\\n /// @notice For native unwrapping\\n receive() external payable {}\\n\\n /// @notice Processes the route generated off-chain. Has a lock\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @param to Where to transfer output tokens\\n /// @param route Route to process\\n /// @return amountOut Actual amount of the output token\\n function processRoute(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function transferValueAndprocessRoute(\\n address transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n transferValueTo.transferNative(amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value of input tokens to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueInput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n \\n /// @notice processes the route and sends amount of output token to \\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueOutput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\\n }\\n\\n /// @notice Processes the route generated off-chain\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteInternal(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) private returns (uint256 amountOut) {\\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\\n\\n uint256 realAmountIn = amountIn;\\n {\\n uint256 step = 0;\\n uint256 stream = InputStream.createStream(route);\\n while (stream.isNotEmpty()) {\\n uint8 commandCode = stream.readUint8();\\n if (commandCode == 1) {\\n uint256 usedAmount = processMyERC20(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 2) processUserERC20(stream, amountIn);\\n else if (commandCode == 3) {\\n uint256 usedAmount = processNative(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 4) processOnePool(stream);\\n else if (commandCode == 5) processInsideBento(stream);\\n else if (commandCode == 6) applyPermit(tokenIn, stream);\\n else revert('RouteProcessor: Unknown command code');\\n ++step;\\n }\\n }\\n\\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\\n if (tokenIn != Utils.NATIVE_ADDRESS)\\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\\n \\n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\\n\\n amountOut = balanceOutFinal - balanceOutInitial;\\n\\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\\n }\\n\\n /// @notice Applies ERC-2612 permit\\n /// @param tokenIn permitted token\\n /// @param stream Streamed program\\n function applyPermit(address tokenIn, uint256 stream) private {\\n uint256 value = stream.readUint();\\n uint256 deadline = stream.readUint();\\n uint8 v = stream.readUint8();\\n bytes32 r = stream.readBytes32();\\n bytes32 s = stream.readBytes32();\\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\\n }\\n }\\n\\n /// @notice Processes native coin: call swap for all pools that swap from native coin\\n /// @param stream Streamed program\\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\\n amountTotal = address(this).balance;\\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token from this contract balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\\n address token = stream.readAddress();\\n amountTotal = IERC20(token).balanceOf(address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n \\n /// @notice Processes ERC20 token from msg.sender balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n /// @param amountTotal Amount of tokens to take from msg.sender\\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\\n address token = stream.readAddress();\\n distributeAndSwap(stream, msg.sender, token, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token for cases when the token has only one output pool\\n /// @notice In this case liquidity is already at pool balance. This is an optimization\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processOnePool(uint256 stream) private {\\n address token = stream.readAddress();\\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\\n }\\n\\n /// @notice Processes Bento tokens \\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processInsideBento(uint256 stream) private {\\n address token = stream.readAddress();\\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n\\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountTotal Total amount of tokenIn for swaps \\n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\\n uint8 num = stream.readUint8();\\n unchecked {\\n for (uint256 i = 0; i < num; ++i) {\\n uint16 share = stream.readUint16();\\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\\n amountTotal -= amount;\\n swap(stream, from, tokenIn, amount);\\n }\\n }\\n }\\n\\n /// @notice Makes swap\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 poolType = stream.readUint8();\\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\\n else revert('RouteProcessor: Unknown pool type');\\n }\\n\\n /// @notice Wraps/unwraps native token\\n /// @param stream [direction & fake, recipient, wrapToken?]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 directionAndFake = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (directionAndFake & 1 == 1) { // wrap native\\n address wrapToken = stream.readAddress();\\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\\n } else { // unwrap native\\n if (directionAndFake & 2 == 0) {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IWETH(tokenIn).withdraw(amountIn);\\n }\\n to.transferNative(amountIn);\\n }\\n }\\n\\n /// @notice Bridge/unbridge tokens to/from Bento\\n /// @param stream [direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (direction > 0) { // outside to Bento\\n // deposit to arbitrary recipient is possible only from address(bentoBox)\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\\n else {\\n // tokens already are at address(bentoBox)\\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\\n bentoBox.strategyData(tokenIn).balance -\\n bentoBox.totals(tokenIn).elastic;\\n }\\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\\n } else { // Bento to outside\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\\n }\\n }\\n\\n /// @notice UniswapV2 pool swap\\n /// @param stream [pool, direction, recipient, fee]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\\n\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\\n\\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\\n\\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\\n }\\n\\n /// @notice Trident pool swap\\n /// @param stream [pool, swapData]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bytes memory swapData = stream.readBytes();\\n\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, pool, amountIn);\\n }\\n \\n IPool(pool).swap(swapData);\\n }\\n\\n /// @notice UniswapV3 pool swap\\n /// @param stream [pool, direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bool zeroForOne = stream.readUint8() > 0;\\n address recipient = stream.readAddress();\\n\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\\n\\n lastCalledPool = pool;\\n IUniswapV3Pool(pool).swap(\\n recipient,\\n zeroForOne,\\n int256(amountIn),\\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\\n abi.encode(tokenIn)\\n );\\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) public {\\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\\n \\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n (address tokenIn) = abi.decode(data, (address));\\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\\n function algebraSwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\\n function pancakeV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 poolType = stream.readUint8();\\n int128 fromIndex = int8(stream.readUint8());\\n int128 toIndex = int8(stream.readUint8());\\n address to = stream.readAddress();\\n address tokenOut = stream.readAddress();\\n\\n uint256 amountOut;\\n if (tokenIn == Utils.NATIVE_ADDRESS) {\\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\\n } else {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IERC20(tokenIn).approveSafe(pool, amountIn);\\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n else {\\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\\n amountOut = balanceAfter - balanceBefore;\\n }\\n }\\n\\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\\n }\\n}\\n\",\"keccak256\":\"0xcd53a7f473f1847d44c42777a194203cbff02b8c761cb2935402401f57c918a2\",\"license\":\"UNLICENSED\"},\"contracts/Utils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\n\\nlibrary Utils {\\n using SafeERC20 for IERC20;\\n\\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n /**\\n * @dev returns user's balance of token (or native)\\n */\\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\\n if (token == NATIVE_ADDRESS) return address(user).balance;\\n else return IERC20(token).balanceOf(user);\\n }\\n\\n /**\\n * @dev transfers native with correct revert bubble up\\n */\\n function transferNative(address to, uint256 amount) internal {\\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\\n if (!success) {\\n assembly {\\n revert(add(32, returnBytes), mload(returnBytes))\\n }\\n }\\n }\\n\\n /**\\n * @dev transfers ERC20 or native\\n */\\n function transferAny(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\\n else IERC20(token).safeTransfer(to, amount);\\n }\\n\\n /**\\n * @dev transfers from ERC20 or transfers native\\n */\\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n (bool success, bytes memory data) = address(token).call(\\n abi.encodeWithSelector(token.approve.selector, spender, amount)\\n );\\n return success && (data.length == 0 || abi.decode(data, (bool)));\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \\n * current allowance are not zero simultaniously (USDT for example). \\n * In second case it tries to set allowance to 0, and then back to amount.\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n return approveStable(token, spender, amount) \\n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\\n }\\n}\\n\",\"keccak256\":\"0x8c8439edc00b403abd3f34be75a06b1fe71152644ae9f19488af596bbc534ffe\",\"license\":\"UNLICENSED\"},\"interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\nstruct StrategyData {\\n uint64 strategyStartDate;\\n uint64 targetPercentage;\\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n function strategyData(address token) external view returns (StrategyData memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0x0c12eba7a5b9d22d37ab8883fe22d6a312a90682809dbd11c43f8e6ceaff73bf\",\"license\":\"UNLICENSED\"},\"interfaces/ICurve.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\ninterface ICurve {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\\n}\\n\\ninterface ICurveLegacy {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\\n}\\n\\n\",\"keccak256\":\"0x3d4940b3583e06dde20f12e92d2f6ac573b3f64bdaa1e8f480656a3763852518\",\"license\":\"UNLICENSED\"},\"interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/ITridentCLPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface ITridentCLPool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bool unwrapBento,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x572376b80c86a94692b0e27e6e63790b763295e32ba1f956c1d331fc1296de8d\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IUniswapV2Pair.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Pair {\\n event Approval(address indexed owner, address indexed spender, uint value);\\n event Transfer(address indexed from, address indexed to, uint value);\\n\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function allowance(address owner, address spender) external view returns (uint);\\n\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address to, uint value) external returns (bool);\\n function transferFrom(address from, address to, uint value) external returns (bool);\\n\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n function nonces(address owner) external view returns (uint);\\n\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n event Mint(address indexed sender, uint amount0, uint amount1);\\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\\n event Swap(\\n address indexed sender,\\n uint amount0In,\\n uint amount1In,\\n uint amount0Out,\\n uint amount1Out,\\n address indexed to\\n );\\n event Sync(uint112 reserve0, uint112 reserve1);\\n\\n function MINIMUM_LIQUIDITY() external pure returns (uint);\\n function factory() external view returns (address);\\n function token0() external view returns (address);\\n function token1() external view returns (address);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\\n function price0CumulativeLast() external view returns (uint);\\n function price1CumulativeLast() external view returns (uint);\\n function kLast() external view returns (uint);\\n\\n function mint(address to) external returns (uint liquidity);\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function skim(address to) external;\\n function sync() external;\\n\\n function initialize(address, address) external;\\n}\",\"keccak256\":\"0x08f9a63b34855eec941be8d36a04424f1a1725a2c030373fcef3afeb480ca385\",\"license\":\"GPL-3.0\"},\"interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IUniswapV3Pool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x2a4d7c6120e613f0e95d4dc8c650efb9b59e3c25c64e3e5c0a379281500f0a79\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IWETH.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0xae8529ae159f784b90fdcd0629bd03bf7b68accc81edccac53357ad08406a378\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}", + "bytecode": "0x60a06040526002805461ffff60a01b191661010160a01b1790553480156200002657600080fd5b50604051620040a3380380620040a383398101604081905262000049916200016e565b6200005433620000eb565b6001600160a01b038216608052600280546001600160a01b031916600117905560005b8151811015620000e25760018060008484815181106200009b576200009b62000257565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000d9816200026d565b91505062000077565b50505062000297565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200015357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200018257600080fd5b6200018d836200013b565b602084810151919350906001600160401b0380821115620001ad57600080fd5b818601915086601f830112620001c257600080fd5b815181811115620001d757620001d762000158565b8060051b604051601f19603f83011681018181108582111715620001ff57620001ff62000158565b6040529182528482019250838101850191898311156200021e57600080fd5b938501935b82851015620002475762000237856200013b565b8452938501939285019262000223565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200029057634e487b7160e01b600052601160045260246000fd5b5060010190565b608051613da3620003006000396000818161018d01528181611798015281816127380152818161279d01528181612807015281816128cc0152818161297901528181612a5d01528181612b6401528181612c1001528181612cdf0152612df10152613da36000f3fe6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "deployedBytecode": "0x6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "devdoc": { + "author": "Ilya Lyalin", + "kind": "dev", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IAlgebraPoolActions#swap call" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the PancakeV3Pool#swap call" + } + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "route": "Route to process", + "to": "Where to transfer output tokens", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IUniswapV3PoolActions#swap call" + } + } + }, + "title": "A route processor for the Sushi Aggregator", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IAlgebraPool#swap." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via PancakeV3Pool#swap." + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "notice": "Processes the route generated off-chain. Has a lock" + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value of input tokens to and then processes the route" + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "processes the route and sends amount of output token to " + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value to and then processes the route" + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 1060, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "priviledgedUsers", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 1062, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "lastCalledPool", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 1065, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "unlocked", + "offset": 20, + "slot": "2", + "type": "t_uint8" + }, + { + "astId": 1068, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "paused", + "offset": 21, + "slot": "2", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/optimism/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json b/protocols/route-processor/deployments/optimism/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json new file mode 100644 index 0000000000..01826e7b93 --- /dev/null +++ b/protocols/route-processor/deployments/optimism/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json @@ -0,0 +1,80 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" + }, + "contracts/InputStream.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" + }, + "contracts/RouteProcessor5.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" + }, + "contracts/Utils.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "interfaces/IBentoBoxMinimal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" + }, + "interfaces/ICurve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" + }, + "interfaces/IPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" + }, + "interfaces/ITridentCLPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/polygon/RouteProcessor5.json b/protocols/route-processor/deployments/polygon/RouteProcessor5.json new file mode 100644 index 0000000000..c89e93a9a4 --- /dev/null +++ b/protocols/route-processor/deployments/polygon/RouteProcessor5.json @@ -0,0 +1,719 @@ +{ + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_bentoBox", + "type": "address" + }, + { + "internalType": "address[]", + "name": "priviledgedUserList", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "MinimalOutputBalanceViolation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Route", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "algebraSwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bentoBox", + "outputs": [ + { + "internalType": "contract IBentoBoxMinimal", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "pancakeV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "priviledgedUsers", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueInput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "priviledge", + "type": "bool" + } + ], + "name": "setPriviledge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "transferValueAndprocessRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x8144b2a94ffaa632cab6c140b9aa56c2dfdeb5552093d431d1715d4ecd163939", + "receipt": { + "to": null, + "from": "0x282607716D9B4fDD0B094d5864fac56313f5e665", + "contractAddress": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "transactionIndex": 70, + "gasUsed": "3489875", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000020000008000000000000000000000008000000001000000000000000000000080000000000000000000040000800001000000000000000100000000000000000000020000000000000000000800000000000000000080000000000000400000000000000000000000000000000000000000002000000000000000080000200000000000000000000000000000000000000000000000000000000000004000000000000002000001000000000000000000000000000000100000000020000000000000040000000000000000000000000000000000000000000000100000", + "blockHash": "0xe24c0d404c7d7d1c7070fc008576527e21291a6a29d3bae0c613b5a3dcc3df99", + "transactionHash": "0x8144b2a94ffaa632cab6c140b9aa56c2dfdeb5552093d431d1715d4ecd163939", + "logs": [ + { + "transactionIndex": 70, + "blockNumber": 59946864, + "transactionHash": "0x8144b2a94ffaa632cab6c140b9aa56c2dfdeb5552093d431d1715d4ecd163939", + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000282607716d9b4fdd0b094d5864fac56313f5e665" + ], + "data": "0x", + "logIndex": 283, + "blockHash": "0xe24c0d404c7d7d1c7070fc008576527e21291a6a29d3bae0c613b5a3dcc3df99" + }, + { + "transactionIndex": 70, + "blockNumber": 59946864, + "transactionHash": "0x8144b2a94ffaa632cab6c140b9aa56c2dfdeb5552093d431d1715d4ecd163939", + "address": "0x0000000000000000000000000000000000001010", + "topics": [ + "0x4dfe1bbbcf077ddc3e01291eea2d5c70c2b422b415d95645b9adcfd678cb1d63", + "0x0000000000000000000000000000000000000000000000000000000000001010", + "0x000000000000000000000000282607716d9b4fdd0b094d5864fac56313f5e665", + "0x000000000000000000000000f0245f6251bef9447a08766b9da2b07b28ad80b0" + ], + "data": "0x0000000000000000000000000000000000000000000000000173f4af4690c40000000000000000000000000000000000000000000000000001e78abd7e6da572000000000000000000000000000000000000000000000295fc789f9a9162e5c00000000000000000000000000000000000000000000000000073960e37dce172000000000000000000000000000000000000000000000295fdec9449d7f3a9c0", + "logIndex": 284, + "blockHash": "0xe24c0d404c7d7d1c7070fc008576527e21291a6a29d3bae0c613b5a3dcc3df99" + } + ], + "blockNumber": 59946864, + "cumulativeGasUsed": "12049532", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000000", + [] + ], + "numDeployments": 1, + "solcInputHash": "e556d43a3caf4f1fb4f12d632d103b28", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bentoBox\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"priviledgedUserList\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"MinimalOutputBalanceViolation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"Route\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"algebraSwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"pancakeV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"priviledgedUsers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"priviledge\",\"type\":\"bool\"}],\"name\":\"setPriviledge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"transferValueAndprocessRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"Ilya Lyalin\",\"kind\":\"dev\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IAlgebraPoolActions#swap call\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the PancakeV3Pool#swap call\"}},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"route\":\"Route to process\",\"to\":\"Where to transfer output tokens\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IUniswapV3PoolActions#swap call\"}}},\"title\":\"A route processor for the Sushi Aggregator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\"},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Processes the route generated off-chain. Has a lock\"},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value of input tokens to and then processes the route\"},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"processes the route and sends amount of output token to \"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value to and then processes the route\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RouteProcessor5.sol\":\"RouteProcessor5\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\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 Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.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 function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\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\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\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 * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\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\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/InputStream.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\n/** @notice Simple read stream */\\nlibrary InputStream {\\n\\n /** @notice Creates stream from data\\n * @param data data\\n */\\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\\n assembly {\\n stream := mload(0x40)\\n mstore(0x40, add(stream, 64))\\n mstore(stream, data)\\n let length := mload(data)\\n mstore(add(stream, 32), add(data, length))\\n }\\n }\\n\\n /** @notice Checks if stream is not empty\\n * @param stream stream\\n */\\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\\n uint256 pos;\\n uint256 finish;\\n assembly {\\n pos := mload(stream)\\n finish := mload(add(stream, 32))\\n }\\n return pos < finish;\\n }\\n\\n /** @notice Reads uint8 from the stream\\n * @param stream stream\\n */\\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 1)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint16 from the stream\\n * @param stream stream\\n */\\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 2)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint24 from the stream\\n * @param stream stream\\n */\\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 3)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint32 from the stream\\n * @param stream stream\\n */\\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 4)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint256 from the stream\\n * @param stream stream\\n */\\n function readUint(uint256 stream) internal pure returns (uint256 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes32 from the stream\\n * @param stream stream\\n */\\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads address from the stream\\n * @param stream stream\\n */\\n function readAddress(uint256 stream) internal pure returns (address res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 20)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes from the stream\\n * @param stream stream\\n */\\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\\n assembly {\\n let pos := mload(stream)\\n res := add(pos, 32)\\n let length := mload(res)\\n mstore(stream, add(res, length))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x24e24bd0e49cbddacbf3b26bcd4bdffac63d11f3259bc05bc93c0835e8ff5300\",\"license\":\"UNLICENSED\"},\"contracts/RouteProcessor5.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '../interfaces/IUniswapV2Pair.sol';\\nimport '../interfaces/IUniswapV3Pool.sol';\\nimport '../interfaces/ITridentCLPool.sol';\\nimport '../interfaces/IBentoBoxMinimal.sol';\\nimport '../interfaces/IPool.sol';\\nimport '../interfaces/IWETH.sol';\\nimport '../interfaces/ICurve.sol';\\nimport './InputStream.sol';\\nimport './Utils.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\\n\\nuint8 constant LOCKED = 2;\\nuint8 constant NOT_LOCKED = 1;\\nuint8 constant PAUSED = 2;\\nuint8 constant NOT_PAUSED = 1;\\n\\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\nuint160 constant MIN_SQRT_RATIO = 4295128739;\\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n/// @title A route processor for the Sushi Aggregator\\n/// @author Ilya Lyalin\\ncontract RouteProcessor5 is Ownable {\\n using SafeERC20 for IERC20;\\n using Utils for IERC20;\\n using Utils for address;\\n using SafeERC20 for IERC20Permit;\\n using InputStream for uint256;\\n\\n event Route(\\n address indexed from, \\n address to, \\n address indexed tokenIn, \\n address indexed tokenOut, \\n uint256 amountIn, \\n uint256 amountOutMin,\\n uint256 amountOut\\n );\\n\\n error MinimalOutputBalanceViolation(uint256 amountOut);\\n\\n IBentoBoxMinimal public immutable bentoBox;\\n mapping (address => bool) public priviledgedUsers;\\n address private lastCalledPool;\\n\\n uint8 private unlocked = NOT_LOCKED;\\n uint8 private paused = NOT_PAUSED;\\n modifier lock() {\\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\\n unlocked = LOCKED;\\n _;\\n unlocked = NOT_LOCKED;\\n }\\n\\n modifier onlyOwnerOrPriviledgedUser() {\\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \\\"RP: caller is not the owner or a privileged user\\\");\\n _;\\n }\\n\\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\\n bentoBox = IBentoBoxMinimal(_bentoBox);\\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n\\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\\n priviledgedUsers[priviledgedUserList[i]] = true;\\n }\\n }\\n\\n function setPriviledge(address user, bool priviledge) external onlyOwner {\\n priviledgedUsers[user] = priviledge;\\n }\\n\\n function pause() external onlyOwnerOrPriviledgedUser {\\n paused = PAUSED;\\n }\\n\\n function resume() external onlyOwnerOrPriviledgedUser {\\n paused = NOT_PAUSED;\\n }\\n\\n /// @notice For native unwrapping\\n receive() external payable {}\\n\\n /// @notice Processes the route generated off-chain. Has a lock\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @param to Where to transfer output tokens\\n /// @param route Route to process\\n /// @return amountOut Actual amount of the output token\\n function processRoute(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function transferValueAndprocessRoute(\\n address transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n transferValueTo.transferNative(amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value of input tokens to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueInput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n \\n /// @notice processes the route and sends amount of output token to \\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueOutput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\\n }\\n\\n /// @notice Processes the route generated off-chain\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteInternal(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) private returns (uint256 amountOut) {\\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\\n\\n uint256 realAmountIn = amountIn;\\n {\\n uint256 step = 0;\\n uint256 stream = InputStream.createStream(route);\\n while (stream.isNotEmpty()) {\\n uint8 commandCode = stream.readUint8();\\n if (commandCode == 1) {\\n uint256 usedAmount = processMyERC20(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 2) processUserERC20(stream, amountIn);\\n else if (commandCode == 3) {\\n uint256 usedAmount = processNative(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 4) processOnePool(stream);\\n else if (commandCode == 5) processInsideBento(stream);\\n else if (commandCode == 6) applyPermit(tokenIn, stream);\\n else revert('RouteProcessor: Unknown command code');\\n ++step;\\n }\\n }\\n\\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\\n if (tokenIn != Utils.NATIVE_ADDRESS)\\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\\n \\n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\\n\\n amountOut = balanceOutFinal - balanceOutInitial;\\n\\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\\n }\\n\\n /// @notice Applies ERC-2612 permit\\n /// @param tokenIn permitted token\\n /// @param stream Streamed program\\n function applyPermit(address tokenIn, uint256 stream) private {\\n uint256 value = stream.readUint();\\n uint256 deadline = stream.readUint();\\n uint8 v = stream.readUint8();\\n bytes32 r = stream.readBytes32();\\n bytes32 s = stream.readBytes32();\\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\\n }\\n }\\n\\n /// @notice Processes native coin: call swap for all pools that swap from native coin\\n /// @param stream Streamed program\\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\\n amountTotal = address(this).balance;\\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token from this contract balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\\n address token = stream.readAddress();\\n amountTotal = IERC20(token).balanceOf(address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n \\n /// @notice Processes ERC20 token from msg.sender balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n /// @param amountTotal Amount of tokens to take from msg.sender\\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\\n address token = stream.readAddress();\\n distributeAndSwap(stream, msg.sender, token, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token for cases when the token has only one output pool\\n /// @notice In this case liquidity is already at pool balance. This is an optimization\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processOnePool(uint256 stream) private {\\n address token = stream.readAddress();\\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\\n }\\n\\n /// @notice Processes Bento tokens \\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processInsideBento(uint256 stream) private {\\n address token = stream.readAddress();\\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n\\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountTotal Total amount of tokenIn for swaps \\n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\\n uint8 num = stream.readUint8();\\n unchecked {\\n for (uint256 i = 0; i < num; ++i) {\\n uint16 share = stream.readUint16();\\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\\n amountTotal -= amount;\\n swap(stream, from, tokenIn, amount);\\n }\\n }\\n }\\n\\n /// @notice Makes swap\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 poolType = stream.readUint8();\\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\\n else revert('RouteProcessor: Unknown pool type');\\n }\\n\\n /// @notice Wraps/unwraps native token\\n /// @param stream [direction & fake, recipient, wrapToken?]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 directionAndFake = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (directionAndFake & 1 == 1) { // wrap native\\n address wrapToken = stream.readAddress();\\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\\n } else { // unwrap native\\n if (directionAndFake & 2 == 0) {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IWETH(tokenIn).withdraw(amountIn);\\n }\\n to.transferNative(amountIn);\\n }\\n }\\n\\n /// @notice Bridge/unbridge tokens to/from Bento\\n /// @param stream [direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (direction > 0) { // outside to Bento\\n // deposit to arbitrary recipient is possible only from address(bentoBox)\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\\n else {\\n // tokens already are at address(bentoBox)\\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\\n bentoBox.strategyData(tokenIn).balance -\\n bentoBox.totals(tokenIn).elastic;\\n }\\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\\n } else { // Bento to outside\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\\n }\\n }\\n\\n /// @notice UniswapV2 pool swap\\n /// @param stream [pool, direction, recipient, fee]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\\n\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\\n\\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\\n\\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\\n }\\n\\n /// @notice Trident pool swap\\n /// @param stream [pool, swapData]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bytes memory swapData = stream.readBytes();\\n\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, pool, amountIn);\\n }\\n \\n IPool(pool).swap(swapData);\\n }\\n\\n /// @notice UniswapV3 pool swap\\n /// @param stream [pool, direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bool zeroForOne = stream.readUint8() > 0;\\n address recipient = stream.readAddress();\\n\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\\n\\n lastCalledPool = pool;\\n IUniswapV3Pool(pool).swap(\\n recipient,\\n zeroForOne,\\n int256(amountIn),\\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\\n abi.encode(tokenIn)\\n );\\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) public {\\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\\n \\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n (address tokenIn) = abi.decode(data, (address));\\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\\n function algebraSwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\\n function pancakeV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 poolType = stream.readUint8();\\n int128 fromIndex = int8(stream.readUint8());\\n int128 toIndex = int8(stream.readUint8());\\n address to = stream.readAddress();\\n address tokenOut = stream.readAddress();\\n\\n uint256 amountOut;\\n if (tokenIn == Utils.NATIVE_ADDRESS) {\\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\\n } else {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IERC20(tokenIn).approveSafe(pool, amountIn);\\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n else {\\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\\n amountOut = balanceAfter - balanceBefore;\\n }\\n }\\n\\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\\n }\\n}\\n\",\"keccak256\":\"0xcd53a7f473f1847d44c42777a194203cbff02b8c761cb2935402401f57c918a2\",\"license\":\"UNLICENSED\"},\"contracts/Utils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\n\\nlibrary Utils {\\n using SafeERC20 for IERC20;\\n\\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n /**\\n * @dev returns user's balance of token (or native)\\n */\\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\\n if (token == NATIVE_ADDRESS) return address(user).balance;\\n else return IERC20(token).balanceOf(user);\\n }\\n\\n /**\\n * @dev transfers native with correct revert bubble up\\n */\\n function transferNative(address to, uint256 amount) internal {\\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\\n if (!success) {\\n assembly {\\n revert(add(32, returnBytes), mload(returnBytes))\\n }\\n }\\n }\\n\\n /**\\n * @dev transfers ERC20 or native\\n */\\n function transferAny(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\\n else IERC20(token).safeTransfer(to, amount);\\n }\\n\\n /**\\n * @dev transfers from ERC20 or transfers native\\n */\\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n (bool success, bytes memory data) = address(token).call(\\n abi.encodeWithSelector(token.approve.selector, spender, amount)\\n );\\n return success && (data.length == 0 || abi.decode(data, (bool)));\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \\n * current allowance are not zero simultaniously (USDT for example). \\n * In second case it tries to set allowance to 0, and then back to amount.\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n return approveStable(token, spender, amount) \\n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\\n }\\n}\\n\",\"keccak256\":\"0x8c8439edc00b403abd3f34be75a06b1fe71152644ae9f19488af596bbc534ffe\",\"license\":\"UNLICENSED\"},\"interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\nstruct StrategyData {\\n uint64 strategyStartDate;\\n uint64 targetPercentage;\\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n function strategyData(address token) external view returns (StrategyData memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0x0c12eba7a5b9d22d37ab8883fe22d6a312a90682809dbd11c43f8e6ceaff73bf\",\"license\":\"UNLICENSED\"},\"interfaces/ICurve.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\ninterface ICurve {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\\n}\\n\\ninterface ICurveLegacy {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\\n}\\n\\n\",\"keccak256\":\"0x3d4940b3583e06dde20f12e92d2f6ac573b3f64bdaa1e8f480656a3763852518\",\"license\":\"UNLICENSED\"},\"interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/ITridentCLPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface ITridentCLPool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bool unwrapBento,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x572376b80c86a94692b0e27e6e63790b763295e32ba1f956c1d331fc1296de8d\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IUniswapV2Pair.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Pair {\\n event Approval(address indexed owner, address indexed spender, uint value);\\n event Transfer(address indexed from, address indexed to, uint value);\\n\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function allowance(address owner, address spender) external view returns (uint);\\n\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address to, uint value) external returns (bool);\\n function transferFrom(address from, address to, uint value) external returns (bool);\\n\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n function nonces(address owner) external view returns (uint);\\n\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n event Mint(address indexed sender, uint amount0, uint amount1);\\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\\n event Swap(\\n address indexed sender,\\n uint amount0In,\\n uint amount1In,\\n uint amount0Out,\\n uint amount1Out,\\n address indexed to\\n );\\n event Sync(uint112 reserve0, uint112 reserve1);\\n\\n function MINIMUM_LIQUIDITY() external pure returns (uint);\\n function factory() external view returns (address);\\n function token0() external view returns (address);\\n function token1() external view returns (address);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\\n function price0CumulativeLast() external view returns (uint);\\n function price1CumulativeLast() external view returns (uint);\\n function kLast() external view returns (uint);\\n\\n function mint(address to) external returns (uint liquidity);\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function skim(address to) external;\\n function sync() external;\\n\\n function initialize(address, address) external;\\n}\",\"keccak256\":\"0x08f9a63b34855eec941be8d36a04424f1a1725a2c030373fcef3afeb480ca385\",\"license\":\"GPL-3.0\"},\"interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IUniswapV3Pool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x2a4d7c6120e613f0e95d4dc8c650efb9b59e3c25c64e3e5c0a379281500f0a79\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IWETH.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0xae8529ae159f784b90fdcd0629bd03bf7b68accc81edccac53357ad08406a378\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}", + "bytecode": "0x60a06040526002805461ffff60a01b191661010160a01b1790553480156200002657600080fd5b50604051620040a3380380620040a383398101604081905262000049916200016e565b6200005433620000eb565b6001600160a01b038216608052600280546001600160a01b031916600117905560005b8151811015620000e25760018060008484815181106200009b576200009b62000257565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000d9816200026d565b91505062000077565b50505062000297565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200015357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200018257600080fd5b6200018d836200013b565b602084810151919350906001600160401b0380821115620001ad57600080fd5b818601915086601f830112620001c257600080fd5b815181811115620001d757620001d762000158565b8060051b604051601f19603f83011681018181108582111715620001ff57620001ff62000158565b6040529182528482019250838101850191898311156200021e57600080fd5b938501935b82851015620002475762000237856200013b565b8452938501939285019262000223565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200029057634e487b7160e01b600052601160045260246000fd5b5060010190565b608051613da3620003006000396000818161018d01528181611798015281816127380152818161279d01528181612807015281816128cc0152818161297901528181612a5d01528181612b6401528181612c1001528181612cdf0152612df10152613da36000f3fe6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "deployedBytecode": "0x6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "devdoc": { + "author": "Ilya Lyalin", + "kind": "dev", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IAlgebraPoolActions#swap call" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the PancakeV3Pool#swap call" + } + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "route": "Route to process", + "to": "Where to transfer output tokens", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IUniswapV3PoolActions#swap call" + } + } + }, + "title": "A route processor for the Sushi Aggregator", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IAlgebraPool#swap." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via PancakeV3Pool#swap." + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "notice": "Processes the route generated off-chain. Has a lock" + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value of input tokens to and then processes the route" + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "processes the route and sends amount of output token to " + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value to and then processes the route" + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 1060, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "priviledgedUsers", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 1062, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "lastCalledPool", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 1065, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "unlocked", + "offset": 20, + "slot": "2", + "type": "t_uint8" + }, + { + "astId": 1068, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "paused", + "offset": 21, + "slot": "2", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/polygon/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json b/protocols/route-processor/deployments/polygon/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json new file mode 100644 index 0000000000..01826e7b93 --- /dev/null +++ b/protocols/route-processor/deployments/polygon/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json @@ -0,0 +1,80 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" + }, + "contracts/InputStream.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" + }, + "contracts/RouteProcessor5.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" + }, + "contracts/Utils.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "interfaces/IBentoBoxMinimal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" + }, + "interfaces/ICurve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" + }, + "interfaces/IPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" + }, + "interfaces/ITridentCLPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/polygonzkevm/RouteProcessor5.json b/protocols/route-processor/deployments/polygonzkevm/RouteProcessor5.json new file mode 100644 index 0000000000..60e3fe9798 --- /dev/null +++ b/protocols/route-processor/deployments/polygonzkevm/RouteProcessor5.json @@ -0,0 +1,704 @@ +{ + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_bentoBox", + "type": "address" + }, + { + "internalType": "address[]", + "name": "priviledgedUserList", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "MinimalOutputBalanceViolation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Route", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "algebraSwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bentoBox", + "outputs": [ + { + "internalType": "contract IBentoBoxMinimal", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "pancakeV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "priviledgedUsers", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueInput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "priviledge", + "type": "bool" + } + ], + "name": "setPriviledge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "transferValueAndprocessRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x371c2e6f5c2e6514c02ef7cbe813ee98b0d860d46a3bfa0abce6ea320c2db6a1", + "receipt": { + "to": null, + "from": "0x282607716D9B4fDD0B094d5864fac56313f5e665", + "contractAddress": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "transactionIndex": 0, + "gasUsed": "3488833", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000020000000000000000000000000000000000000001000000000000000000000000000000000000000000040000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000000000000000000000000000", + "blockHash": "0xdd6d1d81dcaa44aaca97ed382097910887e5fb6d5549639c6bc4d52f8667d753", + "transactionHash": "0x371c2e6f5c2e6514c02ef7cbe813ee98b0d860d46a3bfa0abce6ea320c2db6a1", + "logs": [ + { + "transactionIndex": 0, + "blockNumber": 14646866, + "transactionHash": "0x371c2e6f5c2e6514c02ef7cbe813ee98b0d860d46a3bfa0abce6ea320c2db6a1", + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000282607716d9b4fdd0b094d5864fac56313f5e665" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0xdd6d1d81dcaa44aaca97ed382097910887e5fb6d5549639c6bc4d52f8667d753" + } + ], + "blockNumber": 14646866, + "cumulativeGasUsed": "3488833", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000000", + [] + ], + "numDeployments": 1, + "solcInputHash": "e556d43a3caf4f1fb4f12d632d103b28", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bentoBox\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"priviledgedUserList\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"MinimalOutputBalanceViolation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"Route\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"algebraSwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"pancakeV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"priviledgedUsers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"priviledge\",\"type\":\"bool\"}],\"name\":\"setPriviledge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"transferValueAndprocessRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"Ilya Lyalin\",\"kind\":\"dev\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IAlgebraPoolActions#swap call\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the PancakeV3Pool#swap call\"}},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"route\":\"Route to process\",\"to\":\"Where to transfer output tokens\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IUniswapV3PoolActions#swap call\"}}},\"title\":\"A route processor for the Sushi Aggregator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\"},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Processes the route generated off-chain. Has a lock\"},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value of input tokens to and then processes the route\"},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"processes the route and sends amount of output token to \"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value to and then processes the route\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RouteProcessor5.sol\":\"RouteProcessor5\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\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 Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.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 function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\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\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\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 * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\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\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/InputStream.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\n/** @notice Simple read stream */\\nlibrary InputStream {\\n\\n /** @notice Creates stream from data\\n * @param data data\\n */\\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\\n assembly {\\n stream := mload(0x40)\\n mstore(0x40, add(stream, 64))\\n mstore(stream, data)\\n let length := mload(data)\\n mstore(add(stream, 32), add(data, length))\\n }\\n }\\n\\n /** @notice Checks if stream is not empty\\n * @param stream stream\\n */\\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\\n uint256 pos;\\n uint256 finish;\\n assembly {\\n pos := mload(stream)\\n finish := mload(add(stream, 32))\\n }\\n return pos < finish;\\n }\\n\\n /** @notice Reads uint8 from the stream\\n * @param stream stream\\n */\\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 1)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint16 from the stream\\n * @param stream stream\\n */\\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 2)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint24 from the stream\\n * @param stream stream\\n */\\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 3)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint32 from the stream\\n * @param stream stream\\n */\\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 4)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint256 from the stream\\n * @param stream stream\\n */\\n function readUint(uint256 stream) internal pure returns (uint256 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes32 from the stream\\n * @param stream stream\\n */\\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads address from the stream\\n * @param stream stream\\n */\\n function readAddress(uint256 stream) internal pure returns (address res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 20)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes from the stream\\n * @param stream stream\\n */\\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\\n assembly {\\n let pos := mload(stream)\\n res := add(pos, 32)\\n let length := mload(res)\\n mstore(stream, add(res, length))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x24e24bd0e49cbddacbf3b26bcd4bdffac63d11f3259bc05bc93c0835e8ff5300\",\"license\":\"UNLICENSED\"},\"contracts/RouteProcessor5.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '../interfaces/IUniswapV2Pair.sol';\\nimport '../interfaces/IUniswapV3Pool.sol';\\nimport '../interfaces/ITridentCLPool.sol';\\nimport '../interfaces/IBentoBoxMinimal.sol';\\nimport '../interfaces/IPool.sol';\\nimport '../interfaces/IWETH.sol';\\nimport '../interfaces/ICurve.sol';\\nimport './InputStream.sol';\\nimport './Utils.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\\n\\nuint8 constant LOCKED = 2;\\nuint8 constant NOT_LOCKED = 1;\\nuint8 constant PAUSED = 2;\\nuint8 constant NOT_PAUSED = 1;\\n\\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\nuint160 constant MIN_SQRT_RATIO = 4295128739;\\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n/// @title A route processor for the Sushi Aggregator\\n/// @author Ilya Lyalin\\ncontract RouteProcessor5 is Ownable {\\n using SafeERC20 for IERC20;\\n using Utils for IERC20;\\n using Utils for address;\\n using SafeERC20 for IERC20Permit;\\n using InputStream for uint256;\\n\\n event Route(\\n address indexed from, \\n address to, \\n address indexed tokenIn, \\n address indexed tokenOut, \\n uint256 amountIn, \\n uint256 amountOutMin,\\n uint256 amountOut\\n );\\n\\n error MinimalOutputBalanceViolation(uint256 amountOut);\\n\\n IBentoBoxMinimal public immutable bentoBox;\\n mapping (address => bool) public priviledgedUsers;\\n address private lastCalledPool;\\n\\n uint8 private unlocked = NOT_LOCKED;\\n uint8 private paused = NOT_PAUSED;\\n modifier lock() {\\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\\n unlocked = LOCKED;\\n _;\\n unlocked = NOT_LOCKED;\\n }\\n\\n modifier onlyOwnerOrPriviledgedUser() {\\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \\\"RP: caller is not the owner or a privileged user\\\");\\n _;\\n }\\n\\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\\n bentoBox = IBentoBoxMinimal(_bentoBox);\\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n\\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\\n priviledgedUsers[priviledgedUserList[i]] = true;\\n }\\n }\\n\\n function setPriviledge(address user, bool priviledge) external onlyOwner {\\n priviledgedUsers[user] = priviledge;\\n }\\n\\n function pause() external onlyOwnerOrPriviledgedUser {\\n paused = PAUSED;\\n }\\n\\n function resume() external onlyOwnerOrPriviledgedUser {\\n paused = NOT_PAUSED;\\n }\\n\\n /// @notice For native unwrapping\\n receive() external payable {}\\n\\n /// @notice Processes the route generated off-chain. Has a lock\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @param to Where to transfer output tokens\\n /// @param route Route to process\\n /// @return amountOut Actual amount of the output token\\n function processRoute(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function transferValueAndprocessRoute(\\n address transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n transferValueTo.transferNative(amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value of input tokens to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueInput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n \\n /// @notice processes the route and sends amount of output token to \\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueOutput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\\n }\\n\\n /// @notice Processes the route generated off-chain\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteInternal(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) private returns (uint256 amountOut) {\\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\\n\\n uint256 realAmountIn = amountIn;\\n {\\n uint256 step = 0;\\n uint256 stream = InputStream.createStream(route);\\n while (stream.isNotEmpty()) {\\n uint8 commandCode = stream.readUint8();\\n if (commandCode == 1) {\\n uint256 usedAmount = processMyERC20(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 2) processUserERC20(stream, amountIn);\\n else if (commandCode == 3) {\\n uint256 usedAmount = processNative(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 4) processOnePool(stream);\\n else if (commandCode == 5) processInsideBento(stream);\\n else if (commandCode == 6) applyPermit(tokenIn, stream);\\n else revert('RouteProcessor: Unknown command code');\\n ++step;\\n }\\n }\\n\\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\\n if (tokenIn != Utils.NATIVE_ADDRESS)\\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\\n \\n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\\n\\n amountOut = balanceOutFinal - balanceOutInitial;\\n\\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\\n }\\n\\n /// @notice Applies ERC-2612 permit\\n /// @param tokenIn permitted token\\n /// @param stream Streamed program\\n function applyPermit(address tokenIn, uint256 stream) private {\\n uint256 value = stream.readUint();\\n uint256 deadline = stream.readUint();\\n uint8 v = stream.readUint8();\\n bytes32 r = stream.readBytes32();\\n bytes32 s = stream.readBytes32();\\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\\n }\\n }\\n\\n /// @notice Processes native coin: call swap for all pools that swap from native coin\\n /// @param stream Streamed program\\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\\n amountTotal = address(this).balance;\\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token from this contract balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\\n address token = stream.readAddress();\\n amountTotal = IERC20(token).balanceOf(address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n \\n /// @notice Processes ERC20 token from msg.sender balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n /// @param amountTotal Amount of tokens to take from msg.sender\\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\\n address token = stream.readAddress();\\n distributeAndSwap(stream, msg.sender, token, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token for cases when the token has only one output pool\\n /// @notice In this case liquidity is already at pool balance. This is an optimization\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processOnePool(uint256 stream) private {\\n address token = stream.readAddress();\\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\\n }\\n\\n /// @notice Processes Bento tokens \\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processInsideBento(uint256 stream) private {\\n address token = stream.readAddress();\\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n\\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountTotal Total amount of tokenIn for swaps \\n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\\n uint8 num = stream.readUint8();\\n unchecked {\\n for (uint256 i = 0; i < num; ++i) {\\n uint16 share = stream.readUint16();\\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\\n amountTotal -= amount;\\n swap(stream, from, tokenIn, amount);\\n }\\n }\\n }\\n\\n /// @notice Makes swap\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 poolType = stream.readUint8();\\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\\n else revert('RouteProcessor: Unknown pool type');\\n }\\n\\n /// @notice Wraps/unwraps native token\\n /// @param stream [direction & fake, recipient, wrapToken?]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 directionAndFake = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (directionAndFake & 1 == 1) { // wrap native\\n address wrapToken = stream.readAddress();\\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\\n } else { // unwrap native\\n if (directionAndFake & 2 == 0) {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IWETH(tokenIn).withdraw(amountIn);\\n }\\n to.transferNative(amountIn);\\n }\\n }\\n\\n /// @notice Bridge/unbridge tokens to/from Bento\\n /// @param stream [direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (direction > 0) { // outside to Bento\\n // deposit to arbitrary recipient is possible only from address(bentoBox)\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\\n else {\\n // tokens already are at address(bentoBox)\\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\\n bentoBox.strategyData(tokenIn).balance -\\n bentoBox.totals(tokenIn).elastic;\\n }\\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\\n } else { // Bento to outside\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\\n }\\n }\\n\\n /// @notice UniswapV2 pool swap\\n /// @param stream [pool, direction, recipient, fee]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\\n\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\\n\\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\\n\\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\\n }\\n\\n /// @notice Trident pool swap\\n /// @param stream [pool, swapData]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bytes memory swapData = stream.readBytes();\\n\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, pool, amountIn);\\n }\\n \\n IPool(pool).swap(swapData);\\n }\\n\\n /// @notice UniswapV3 pool swap\\n /// @param stream [pool, direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bool zeroForOne = stream.readUint8() > 0;\\n address recipient = stream.readAddress();\\n\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\\n\\n lastCalledPool = pool;\\n IUniswapV3Pool(pool).swap(\\n recipient,\\n zeroForOne,\\n int256(amountIn),\\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\\n abi.encode(tokenIn)\\n );\\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) public {\\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\\n \\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n (address tokenIn) = abi.decode(data, (address));\\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\\n function algebraSwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\\n function pancakeV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 poolType = stream.readUint8();\\n int128 fromIndex = int8(stream.readUint8());\\n int128 toIndex = int8(stream.readUint8());\\n address to = stream.readAddress();\\n address tokenOut = stream.readAddress();\\n\\n uint256 amountOut;\\n if (tokenIn == Utils.NATIVE_ADDRESS) {\\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\\n } else {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IERC20(tokenIn).approveSafe(pool, amountIn);\\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n else {\\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\\n amountOut = balanceAfter - balanceBefore;\\n }\\n }\\n\\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\\n }\\n}\\n\",\"keccak256\":\"0xcd53a7f473f1847d44c42777a194203cbff02b8c761cb2935402401f57c918a2\",\"license\":\"UNLICENSED\"},\"contracts/Utils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\n\\nlibrary Utils {\\n using SafeERC20 for IERC20;\\n\\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n /**\\n * @dev returns user's balance of token (or native)\\n */\\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\\n if (token == NATIVE_ADDRESS) return address(user).balance;\\n else return IERC20(token).balanceOf(user);\\n }\\n\\n /**\\n * @dev transfers native with correct revert bubble up\\n */\\n function transferNative(address to, uint256 amount) internal {\\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\\n if (!success) {\\n assembly {\\n revert(add(32, returnBytes), mload(returnBytes))\\n }\\n }\\n }\\n\\n /**\\n * @dev transfers ERC20 or native\\n */\\n function transferAny(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\\n else IERC20(token).safeTransfer(to, amount);\\n }\\n\\n /**\\n * @dev transfers from ERC20 or transfers native\\n */\\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n (bool success, bytes memory data) = address(token).call(\\n abi.encodeWithSelector(token.approve.selector, spender, amount)\\n );\\n return success && (data.length == 0 || abi.decode(data, (bool)));\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \\n * current allowance are not zero simultaniously (USDT for example). \\n * In second case it tries to set allowance to 0, and then back to amount.\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n return approveStable(token, spender, amount) \\n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\\n }\\n}\\n\",\"keccak256\":\"0x8c8439edc00b403abd3f34be75a06b1fe71152644ae9f19488af596bbc534ffe\",\"license\":\"UNLICENSED\"},\"interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\nstruct StrategyData {\\n uint64 strategyStartDate;\\n uint64 targetPercentage;\\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n function strategyData(address token) external view returns (StrategyData memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0x0c12eba7a5b9d22d37ab8883fe22d6a312a90682809dbd11c43f8e6ceaff73bf\",\"license\":\"UNLICENSED\"},\"interfaces/ICurve.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\ninterface ICurve {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\\n}\\n\\ninterface ICurveLegacy {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\\n}\\n\\n\",\"keccak256\":\"0x3d4940b3583e06dde20f12e92d2f6ac573b3f64bdaa1e8f480656a3763852518\",\"license\":\"UNLICENSED\"},\"interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/ITridentCLPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface ITridentCLPool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bool unwrapBento,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x572376b80c86a94692b0e27e6e63790b763295e32ba1f956c1d331fc1296de8d\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IUniswapV2Pair.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Pair {\\n event Approval(address indexed owner, address indexed spender, uint value);\\n event Transfer(address indexed from, address indexed to, uint value);\\n\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function allowance(address owner, address spender) external view returns (uint);\\n\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address to, uint value) external returns (bool);\\n function transferFrom(address from, address to, uint value) external returns (bool);\\n\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n function nonces(address owner) external view returns (uint);\\n\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n event Mint(address indexed sender, uint amount0, uint amount1);\\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\\n event Swap(\\n address indexed sender,\\n uint amount0In,\\n uint amount1In,\\n uint amount0Out,\\n uint amount1Out,\\n address indexed to\\n );\\n event Sync(uint112 reserve0, uint112 reserve1);\\n\\n function MINIMUM_LIQUIDITY() external pure returns (uint);\\n function factory() external view returns (address);\\n function token0() external view returns (address);\\n function token1() external view returns (address);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\\n function price0CumulativeLast() external view returns (uint);\\n function price1CumulativeLast() external view returns (uint);\\n function kLast() external view returns (uint);\\n\\n function mint(address to) external returns (uint liquidity);\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function skim(address to) external;\\n function sync() external;\\n\\n function initialize(address, address) external;\\n}\",\"keccak256\":\"0x08f9a63b34855eec941be8d36a04424f1a1725a2c030373fcef3afeb480ca385\",\"license\":\"GPL-3.0\"},\"interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IUniswapV3Pool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x2a4d7c6120e613f0e95d4dc8c650efb9b59e3c25c64e3e5c0a379281500f0a79\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IWETH.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0xae8529ae159f784b90fdcd0629bd03bf7b68accc81edccac53357ad08406a378\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}", + "bytecode": "0x60a06040526002805461ffff60a01b191661010160a01b1790553480156200002657600080fd5b50604051620040a3380380620040a383398101604081905262000049916200016e565b6200005433620000eb565b6001600160a01b038216608052600280546001600160a01b031916600117905560005b8151811015620000e25760018060008484815181106200009b576200009b62000257565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000d9816200026d565b91505062000077565b50505062000297565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200015357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200018257600080fd5b6200018d836200013b565b602084810151919350906001600160401b0380821115620001ad57600080fd5b818601915086601f830112620001c257600080fd5b815181811115620001d757620001d762000158565b8060051b604051601f19603f83011681018181108582111715620001ff57620001ff62000158565b6040529182528482019250838101850191898311156200021e57600080fd5b938501935b82851015620002475762000237856200013b565b8452938501939285019262000223565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200029057634e487b7160e01b600052601160045260246000fd5b5060010190565b608051613da3620003006000396000818161018d01528181611798015281816127380152818161279d01528181612807015281816128cc0152818161297901528181612a5d01528181612b6401528181612c1001528181612cdf0152612df10152613da36000f3fe6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "deployedBytecode": "0x6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "devdoc": { + "author": "Ilya Lyalin", + "kind": "dev", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IAlgebraPoolActions#swap call" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the PancakeV3Pool#swap call" + } + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "route": "Route to process", + "to": "Where to transfer output tokens", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IUniswapV3PoolActions#swap call" + } + } + }, + "title": "A route processor for the Sushi Aggregator", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IAlgebraPool#swap." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via PancakeV3Pool#swap." + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "notice": "Processes the route generated off-chain. Has a lock" + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value of input tokens to and then processes the route" + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "processes the route and sends amount of output token to " + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value to and then processes the route" + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 1060, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "priviledgedUsers", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 1062, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "lastCalledPool", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 1065, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "unlocked", + "offset": 20, + "slot": "2", + "type": "t_uint8" + }, + { + "astId": 1068, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "paused", + "offset": 21, + "slot": "2", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/polygonzkevm/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json b/protocols/route-processor/deployments/polygonzkevm/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json new file mode 100644 index 0000000000..01826e7b93 --- /dev/null +++ b/protocols/route-processor/deployments/polygonzkevm/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json @@ -0,0 +1,80 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" + }, + "contracts/InputStream.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" + }, + "contracts/RouteProcessor5.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" + }, + "contracts/Utils.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "interfaces/IBentoBoxMinimal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" + }, + "interfaces/ICurve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" + }, + "interfaces/IPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" + }, + "interfaces/ITridentCLPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/rootstock/RouteProcessor5.json b/protocols/route-processor/deployments/rootstock/RouteProcessor5.json new file mode 100644 index 0000000000..e4fece8039 --- /dev/null +++ b/protocols/route-processor/deployments/rootstock/RouteProcessor5.json @@ -0,0 +1,704 @@ +{ + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_bentoBox", + "type": "address" + }, + { + "internalType": "address[]", + "name": "priviledgedUserList", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "MinimalOutputBalanceViolation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Route", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "algebraSwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bentoBox", + "outputs": [ + { + "internalType": "contract IBentoBoxMinimal", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "pancakeV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "priviledgedUsers", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueInput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "priviledge", + "type": "bool" + } + ], + "name": "setPriviledge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "transferValueAndprocessRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x9b0eb11f9c7ffd8bd04067045b073f0ae53d793bdb6d21ce4419068ee9a452a0", + "receipt": { + "to": null, + "from": "0x282607716D9B4fDD0B094d5864fac56313f5e665", + "contractAddress": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "transactionIndex": 1, + "gasUsed": "3490033", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000020000000000000000000000000000000000000001000000000000000000000000000000000000000000040000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000000000000000000000000000", + "blockHash": "0x3cbfba73acee90071500b6a832caed5762ca759506d0aa50fd0daac42583a95d", + "transactionHash": "0x9b0eb11f9c7ffd8bd04067045b073f0ae53d793bdb6d21ce4419068ee9a452a0", + "logs": [ + { + "transactionIndex": 1, + "blockNumber": 6563126, + "transactionHash": "0x9b0eb11f9c7ffd8bd04067045b073f0ae53d793bdb6d21ce4419068ee9a452a0", + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000282607716d9b4fdd0b094d5864fac56313f5e665" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0x3cbfba73acee90071500b6a832caed5762ca759506d0aa50fd0daac42583a95d" + } + ], + "blockNumber": 6563126, + "cumulativeGasUsed": "3547106", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000000", + [] + ], + "numDeployments": 1, + "solcInputHash": "e556d43a3caf4f1fb4f12d632d103b28", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bentoBox\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"priviledgedUserList\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"MinimalOutputBalanceViolation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"Route\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"algebraSwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"pancakeV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"priviledgedUsers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"priviledge\",\"type\":\"bool\"}],\"name\":\"setPriviledge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"transferValueAndprocessRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"Ilya Lyalin\",\"kind\":\"dev\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IAlgebraPoolActions#swap call\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the PancakeV3Pool#swap call\"}},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"route\":\"Route to process\",\"to\":\"Where to transfer output tokens\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IUniswapV3PoolActions#swap call\"}}},\"title\":\"A route processor for the Sushi Aggregator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\"},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Processes the route generated off-chain. Has a lock\"},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value of input tokens to and then processes the route\"},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"processes the route and sends amount of output token to \"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value to and then processes the route\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RouteProcessor5.sol\":\"RouteProcessor5\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\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 Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.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 function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\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\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\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 * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\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\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/InputStream.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\n/** @notice Simple read stream */\\nlibrary InputStream {\\n\\n /** @notice Creates stream from data\\n * @param data data\\n */\\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\\n assembly {\\n stream := mload(0x40)\\n mstore(0x40, add(stream, 64))\\n mstore(stream, data)\\n let length := mload(data)\\n mstore(add(stream, 32), add(data, length))\\n }\\n }\\n\\n /** @notice Checks if stream is not empty\\n * @param stream stream\\n */\\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\\n uint256 pos;\\n uint256 finish;\\n assembly {\\n pos := mload(stream)\\n finish := mload(add(stream, 32))\\n }\\n return pos < finish;\\n }\\n\\n /** @notice Reads uint8 from the stream\\n * @param stream stream\\n */\\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 1)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint16 from the stream\\n * @param stream stream\\n */\\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 2)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint24 from the stream\\n * @param stream stream\\n */\\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 3)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint32 from the stream\\n * @param stream stream\\n */\\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 4)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint256 from the stream\\n * @param stream stream\\n */\\n function readUint(uint256 stream) internal pure returns (uint256 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes32 from the stream\\n * @param stream stream\\n */\\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads address from the stream\\n * @param stream stream\\n */\\n function readAddress(uint256 stream) internal pure returns (address res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 20)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes from the stream\\n * @param stream stream\\n */\\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\\n assembly {\\n let pos := mload(stream)\\n res := add(pos, 32)\\n let length := mload(res)\\n mstore(stream, add(res, length))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x24e24bd0e49cbddacbf3b26bcd4bdffac63d11f3259bc05bc93c0835e8ff5300\",\"license\":\"UNLICENSED\"},\"contracts/RouteProcessor5.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '../interfaces/IUniswapV2Pair.sol';\\nimport '../interfaces/IUniswapV3Pool.sol';\\nimport '../interfaces/ITridentCLPool.sol';\\nimport '../interfaces/IBentoBoxMinimal.sol';\\nimport '../interfaces/IPool.sol';\\nimport '../interfaces/IWETH.sol';\\nimport '../interfaces/ICurve.sol';\\nimport './InputStream.sol';\\nimport './Utils.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\\n\\nuint8 constant LOCKED = 2;\\nuint8 constant NOT_LOCKED = 1;\\nuint8 constant PAUSED = 2;\\nuint8 constant NOT_PAUSED = 1;\\n\\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\nuint160 constant MIN_SQRT_RATIO = 4295128739;\\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n/// @title A route processor for the Sushi Aggregator\\n/// @author Ilya Lyalin\\ncontract RouteProcessor5 is Ownable {\\n using SafeERC20 for IERC20;\\n using Utils for IERC20;\\n using Utils for address;\\n using SafeERC20 for IERC20Permit;\\n using InputStream for uint256;\\n\\n event Route(\\n address indexed from, \\n address to, \\n address indexed tokenIn, \\n address indexed tokenOut, \\n uint256 amountIn, \\n uint256 amountOutMin,\\n uint256 amountOut\\n );\\n\\n error MinimalOutputBalanceViolation(uint256 amountOut);\\n\\n IBentoBoxMinimal public immutable bentoBox;\\n mapping (address => bool) public priviledgedUsers;\\n address private lastCalledPool;\\n\\n uint8 private unlocked = NOT_LOCKED;\\n uint8 private paused = NOT_PAUSED;\\n modifier lock() {\\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\\n unlocked = LOCKED;\\n _;\\n unlocked = NOT_LOCKED;\\n }\\n\\n modifier onlyOwnerOrPriviledgedUser() {\\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \\\"RP: caller is not the owner or a privileged user\\\");\\n _;\\n }\\n\\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\\n bentoBox = IBentoBoxMinimal(_bentoBox);\\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n\\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\\n priviledgedUsers[priviledgedUserList[i]] = true;\\n }\\n }\\n\\n function setPriviledge(address user, bool priviledge) external onlyOwner {\\n priviledgedUsers[user] = priviledge;\\n }\\n\\n function pause() external onlyOwnerOrPriviledgedUser {\\n paused = PAUSED;\\n }\\n\\n function resume() external onlyOwnerOrPriviledgedUser {\\n paused = NOT_PAUSED;\\n }\\n\\n /// @notice For native unwrapping\\n receive() external payable {}\\n\\n /// @notice Processes the route generated off-chain. Has a lock\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @param to Where to transfer output tokens\\n /// @param route Route to process\\n /// @return amountOut Actual amount of the output token\\n function processRoute(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function transferValueAndprocessRoute(\\n address transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n transferValueTo.transferNative(amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value of input tokens to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueInput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n \\n /// @notice processes the route and sends amount of output token to \\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueOutput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\\n }\\n\\n /// @notice Processes the route generated off-chain\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteInternal(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) private returns (uint256 amountOut) {\\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\\n\\n uint256 realAmountIn = amountIn;\\n {\\n uint256 step = 0;\\n uint256 stream = InputStream.createStream(route);\\n while (stream.isNotEmpty()) {\\n uint8 commandCode = stream.readUint8();\\n if (commandCode == 1) {\\n uint256 usedAmount = processMyERC20(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 2) processUserERC20(stream, amountIn);\\n else if (commandCode == 3) {\\n uint256 usedAmount = processNative(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 4) processOnePool(stream);\\n else if (commandCode == 5) processInsideBento(stream);\\n else if (commandCode == 6) applyPermit(tokenIn, stream);\\n else revert('RouteProcessor: Unknown command code');\\n ++step;\\n }\\n }\\n\\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\\n if (tokenIn != Utils.NATIVE_ADDRESS)\\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\\n \\n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\\n\\n amountOut = balanceOutFinal - balanceOutInitial;\\n\\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\\n }\\n\\n /// @notice Applies ERC-2612 permit\\n /// @param tokenIn permitted token\\n /// @param stream Streamed program\\n function applyPermit(address tokenIn, uint256 stream) private {\\n uint256 value = stream.readUint();\\n uint256 deadline = stream.readUint();\\n uint8 v = stream.readUint8();\\n bytes32 r = stream.readBytes32();\\n bytes32 s = stream.readBytes32();\\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\\n }\\n }\\n\\n /// @notice Processes native coin: call swap for all pools that swap from native coin\\n /// @param stream Streamed program\\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\\n amountTotal = address(this).balance;\\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token from this contract balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\\n address token = stream.readAddress();\\n amountTotal = IERC20(token).balanceOf(address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n \\n /// @notice Processes ERC20 token from msg.sender balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n /// @param amountTotal Amount of tokens to take from msg.sender\\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\\n address token = stream.readAddress();\\n distributeAndSwap(stream, msg.sender, token, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token for cases when the token has only one output pool\\n /// @notice In this case liquidity is already at pool balance. This is an optimization\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processOnePool(uint256 stream) private {\\n address token = stream.readAddress();\\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\\n }\\n\\n /// @notice Processes Bento tokens \\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processInsideBento(uint256 stream) private {\\n address token = stream.readAddress();\\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n\\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountTotal Total amount of tokenIn for swaps \\n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\\n uint8 num = stream.readUint8();\\n unchecked {\\n for (uint256 i = 0; i < num; ++i) {\\n uint16 share = stream.readUint16();\\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\\n amountTotal -= amount;\\n swap(stream, from, tokenIn, amount);\\n }\\n }\\n }\\n\\n /// @notice Makes swap\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 poolType = stream.readUint8();\\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\\n else revert('RouteProcessor: Unknown pool type');\\n }\\n\\n /// @notice Wraps/unwraps native token\\n /// @param stream [direction & fake, recipient, wrapToken?]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 directionAndFake = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (directionAndFake & 1 == 1) { // wrap native\\n address wrapToken = stream.readAddress();\\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\\n } else { // unwrap native\\n if (directionAndFake & 2 == 0) {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IWETH(tokenIn).withdraw(amountIn);\\n }\\n to.transferNative(amountIn);\\n }\\n }\\n\\n /// @notice Bridge/unbridge tokens to/from Bento\\n /// @param stream [direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (direction > 0) { // outside to Bento\\n // deposit to arbitrary recipient is possible only from address(bentoBox)\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\\n else {\\n // tokens already are at address(bentoBox)\\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\\n bentoBox.strategyData(tokenIn).balance -\\n bentoBox.totals(tokenIn).elastic;\\n }\\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\\n } else { // Bento to outside\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\\n }\\n }\\n\\n /// @notice UniswapV2 pool swap\\n /// @param stream [pool, direction, recipient, fee]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\\n\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\\n\\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\\n\\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\\n }\\n\\n /// @notice Trident pool swap\\n /// @param stream [pool, swapData]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bytes memory swapData = stream.readBytes();\\n\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, pool, amountIn);\\n }\\n \\n IPool(pool).swap(swapData);\\n }\\n\\n /// @notice UniswapV3 pool swap\\n /// @param stream [pool, direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bool zeroForOne = stream.readUint8() > 0;\\n address recipient = stream.readAddress();\\n\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\\n\\n lastCalledPool = pool;\\n IUniswapV3Pool(pool).swap(\\n recipient,\\n zeroForOne,\\n int256(amountIn),\\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\\n abi.encode(tokenIn)\\n );\\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) public {\\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\\n \\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n (address tokenIn) = abi.decode(data, (address));\\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\\n function algebraSwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\\n function pancakeV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 poolType = stream.readUint8();\\n int128 fromIndex = int8(stream.readUint8());\\n int128 toIndex = int8(stream.readUint8());\\n address to = stream.readAddress();\\n address tokenOut = stream.readAddress();\\n\\n uint256 amountOut;\\n if (tokenIn == Utils.NATIVE_ADDRESS) {\\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\\n } else {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IERC20(tokenIn).approveSafe(pool, amountIn);\\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n else {\\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\\n amountOut = balanceAfter - balanceBefore;\\n }\\n }\\n\\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\\n }\\n}\\n\",\"keccak256\":\"0xcd53a7f473f1847d44c42777a194203cbff02b8c761cb2935402401f57c918a2\",\"license\":\"UNLICENSED\"},\"contracts/Utils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\n\\nlibrary Utils {\\n using SafeERC20 for IERC20;\\n\\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n /**\\n * @dev returns user's balance of token (or native)\\n */\\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\\n if (token == NATIVE_ADDRESS) return address(user).balance;\\n else return IERC20(token).balanceOf(user);\\n }\\n\\n /**\\n * @dev transfers native with correct revert bubble up\\n */\\n function transferNative(address to, uint256 amount) internal {\\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\\n if (!success) {\\n assembly {\\n revert(add(32, returnBytes), mload(returnBytes))\\n }\\n }\\n }\\n\\n /**\\n * @dev transfers ERC20 or native\\n */\\n function transferAny(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\\n else IERC20(token).safeTransfer(to, amount);\\n }\\n\\n /**\\n * @dev transfers from ERC20 or transfers native\\n */\\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n (bool success, bytes memory data) = address(token).call(\\n abi.encodeWithSelector(token.approve.selector, spender, amount)\\n );\\n return success && (data.length == 0 || abi.decode(data, (bool)));\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \\n * current allowance are not zero simultaniously (USDT for example). \\n * In second case it tries to set allowance to 0, and then back to amount.\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n return approveStable(token, spender, amount) \\n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\\n }\\n}\\n\",\"keccak256\":\"0x8c8439edc00b403abd3f34be75a06b1fe71152644ae9f19488af596bbc534ffe\",\"license\":\"UNLICENSED\"},\"interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\nstruct StrategyData {\\n uint64 strategyStartDate;\\n uint64 targetPercentage;\\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n function strategyData(address token) external view returns (StrategyData memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0x0c12eba7a5b9d22d37ab8883fe22d6a312a90682809dbd11c43f8e6ceaff73bf\",\"license\":\"UNLICENSED\"},\"interfaces/ICurve.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\ninterface ICurve {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\\n}\\n\\ninterface ICurveLegacy {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\\n}\\n\\n\",\"keccak256\":\"0x3d4940b3583e06dde20f12e92d2f6ac573b3f64bdaa1e8f480656a3763852518\",\"license\":\"UNLICENSED\"},\"interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/ITridentCLPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface ITridentCLPool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bool unwrapBento,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x572376b80c86a94692b0e27e6e63790b763295e32ba1f956c1d331fc1296de8d\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IUniswapV2Pair.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Pair {\\n event Approval(address indexed owner, address indexed spender, uint value);\\n event Transfer(address indexed from, address indexed to, uint value);\\n\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function allowance(address owner, address spender) external view returns (uint);\\n\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address to, uint value) external returns (bool);\\n function transferFrom(address from, address to, uint value) external returns (bool);\\n\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n function nonces(address owner) external view returns (uint);\\n\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n event Mint(address indexed sender, uint amount0, uint amount1);\\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\\n event Swap(\\n address indexed sender,\\n uint amount0In,\\n uint amount1In,\\n uint amount0Out,\\n uint amount1Out,\\n address indexed to\\n );\\n event Sync(uint112 reserve0, uint112 reserve1);\\n\\n function MINIMUM_LIQUIDITY() external pure returns (uint);\\n function factory() external view returns (address);\\n function token0() external view returns (address);\\n function token1() external view returns (address);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\\n function price0CumulativeLast() external view returns (uint);\\n function price1CumulativeLast() external view returns (uint);\\n function kLast() external view returns (uint);\\n\\n function mint(address to) external returns (uint liquidity);\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function skim(address to) external;\\n function sync() external;\\n\\n function initialize(address, address) external;\\n}\",\"keccak256\":\"0x08f9a63b34855eec941be8d36a04424f1a1725a2c030373fcef3afeb480ca385\",\"license\":\"GPL-3.0\"},\"interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IUniswapV3Pool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x2a4d7c6120e613f0e95d4dc8c650efb9b59e3c25c64e3e5c0a379281500f0a79\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IWETH.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0xae8529ae159f784b90fdcd0629bd03bf7b68accc81edccac53357ad08406a378\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}", + "bytecode": "0x60a06040526002805461ffff60a01b191661010160a01b1790553480156200002657600080fd5b50604051620040a3380380620040a383398101604081905262000049916200016e565b6200005433620000eb565b6001600160a01b038216608052600280546001600160a01b031916600117905560005b8151811015620000e25760018060008484815181106200009b576200009b62000257565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000d9816200026d565b91505062000077565b50505062000297565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200015357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200018257600080fd5b6200018d836200013b565b602084810151919350906001600160401b0380821115620001ad57600080fd5b818601915086601f830112620001c257600080fd5b815181811115620001d757620001d762000158565b8060051b604051601f19603f83011681018181108582111715620001ff57620001ff62000158565b6040529182528482019250838101850191898311156200021e57600080fd5b938501935b82851015620002475762000237856200013b565b8452938501939285019262000223565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200029057634e487b7160e01b600052601160045260246000fd5b5060010190565b608051613da3620003006000396000818161018d01528181611798015281816127380152818161279d01528181612807015281816128cc0152818161297901528181612a5d01528181612b6401528181612c1001528181612cdf0152612df10152613da36000f3fe6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "deployedBytecode": "0x6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "devdoc": { + "author": "Ilya Lyalin", + "kind": "dev", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IAlgebraPoolActions#swap call" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the PancakeV3Pool#swap call" + } + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "route": "Route to process", + "to": "Where to transfer output tokens", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IUniswapV3PoolActions#swap call" + } + } + }, + "title": "A route processor for the Sushi Aggregator", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IAlgebraPool#swap." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via PancakeV3Pool#swap." + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "notice": "Processes the route generated off-chain. Has a lock" + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value of input tokens to and then processes the route" + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "processes the route and sends amount of output token to " + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value to and then processes the route" + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 1060, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "priviledgedUsers", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 1062, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "lastCalledPool", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 1065, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "unlocked", + "offset": 20, + "slot": "2", + "type": "t_uint8" + }, + { + "astId": 1068, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "paused", + "offset": 21, + "slot": "2", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/rootstock/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json b/protocols/route-processor/deployments/rootstock/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json new file mode 100644 index 0000000000..01826e7b93 --- /dev/null +++ b/protocols/route-processor/deployments/rootstock/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json @@ -0,0 +1,80 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" + }, + "contracts/InputStream.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" + }, + "contracts/RouteProcessor5.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" + }, + "contracts/Utils.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "interfaces/IBentoBoxMinimal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" + }, + "interfaces/ICurve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" + }, + "interfaces/IPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" + }, + "interfaces/ITridentCLPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/scroll/RouteProcessor5.json b/protocols/route-processor/deployments/scroll/RouteProcessor5.json new file mode 100644 index 0000000000..07a7bf509a --- /dev/null +++ b/protocols/route-processor/deployments/scroll/RouteProcessor5.json @@ -0,0 +1,704 @@ +{ + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_bentoBox", + "type": "address" + }, + { + "internalType": "address[]", + "name": "priviledgedUserList", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "MinimalOutputBalanceViolation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Route", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "algebraSwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bentoBox", + "outputs": [ + { + "internalType": "contract IBentoBoxMinimal", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "pancakeV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "priviledgedUsers", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueInput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "priviledge", + "type": "bool" + } + ], + "name": "setPriviledge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "transferValueAndprocessRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x4fb1e023c56999bc5147cf1029764b0750eddbd6a466f4a4eebafcb9607a4ccc", + "receipt": { + "to": null, + "from": "0x282607716D9B4fDD0B094d5864fac56313f5e665", + "contractAddress": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "transactionIndex": 4, + "gasUsed": "3489875", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000020000000000000000000000000000000000000001000000000000000000000000000000000000000000040000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000000000000000000000000000", + "blockHash": "0xbd20c7816dc8d497d052fbc9a8287d232126008898c218895d11909f2f0658c3", + "transactionHash": "0x4fb1e023c56999bc5147cf1029764b0750eddbd6a466f4a4eebafcb9607a4ccc", + "logs": [ + { + "transactionIndex": 4, + "blockNumber": 7879218, + "transactionHash": "0x4fb1e023c56999bc5147cf1029764b0750eddbd6a466f4a4eebafcb9607a4ccc", + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000282607716d9b4fdd0b094d5864fac56313f5e665" + ], + "data": "0x", + "logIndex": 24, + "blockHash": "0xbd20c7816dc8d497d052fbc9a8287d232126008898c218895d11909f2f0658c3" + } + ], + "blockNumber": 7879218, + "cumulativeGasUsed": "6011779", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000000", + [] + ], + "numDeployments": 1, + "solcInputHash": "e556d43a3caf4f1fb4f12d632d103b28", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bentoBox\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"priviledgedUserList\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"MinimalOutputBalanceViolation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"Route\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"algebraSwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"pancakeV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"priviledgedUsers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"priviledge\",\"type\":\"bool\"}],\"name\":\"setPriviledge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"transferValueAndprocessRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"Ilya Lyalin\",\"kind\":\"dev\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IAlgebraPoolActions#swap call\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the PancakeV3Pool#swap call\"}},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"route\":\"Route to process\",\"to\":\"Where to transfer output tokens\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IUniswapV3PoolActions#swap call\"}}},\"title\":\"A route processor for the Sushi Aggregator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\"},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Processes the route generated off-chain. Has a lock\"},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value of input tokens to and then processes the route\"},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"processes the route and sends amount of output token to \"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value to and then processes the route\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RouteProcessor5.sol\":\"RouteProcessor5\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\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 Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.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 function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\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\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\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 * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\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\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/InputStream.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\n/** @notice Simple read stream */\\nlibrary InputStream {\\n\\n /** @notice Creates stream from data\\n * @param data data\\n */\\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\\n assembly {\\n stream := mload(0x40)\\n mstore(0x40, add(stream, 64))\\n mstore(stream, data)\\n let length := mload(data)\\n mstore(add(stream, 32), add(data, length))\\n }\\n }\\n\\n /** @notice Checks if stream is not empty\\n * @param stream stream\\n */\\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\\n uint256 pos;\\n uint256 finish;\\n assembly {\\n pos := mload(stream)\\n finish := mload(add(stream, 32))\\n }\\n return pos < finish;\\n }\\n\\n /** @notice Reads uint8 from the stream\\n * @param stream stream\\n */\\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 1)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint16 from the stream\\n * @param stream stream\\n */\\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 2)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint24 from the stream\\n * @param stream stream\\n */\\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 3)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint32 from the stream\\n * @param stream stream\\n */\\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 4)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint256 from the stream\\n * @param stream stream\\n */\\n function readUint(uint256 stream) internal pure returns (uint256 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes32 from the stream\\n * @param stream stream\\n */\\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads address from the stream\\n * @param stream stream\\n */\\n function readAddress(uint256 stream) internal pure returns (address res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 20)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes from the stream\\n * @param stream stream\\n */\\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\\n assembly {\\n let pos := mload(stream)\\n res := add(pos, 32)\\n let length := mload(res)\\n mstore(stream, add(res, length))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x24e24bd0e49cbddacbf3b26bcd4bdffac63d11f3259bc05bc93c0835e8ff5300\",\"license\":\"UNLICENSED\"},\"contracts/RouteProcessor5.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '../interfaces/IUniswapV2Pair.sol';\\nimport '../interfaces/IUniswapV3Pool.sol';\\nimport '../interfaces/ITridentCLPool.sol';\\nimport '../interfaces/IBentoBoxMinimal.sol';\\nimport '../interfaces/IPool.sol';\\nimport '../interfaces/IWETH.sol';\\nimport '../interfaces/ICurve.sol';\\nimport './InputStream.sol';\\nimport './Utils.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\\n\\nuint8 constant LOCKED = 2;\\nuint8 constant NOT_LOCKED = 1;\\nuint8 constant PAUSED = 2;\\nuint8 constant NOT_PAUSED = 1;\\n\\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\nuint160 constant MIN_SQRT_RATIO = 4295128739;\\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n/// @title A route processor for the Sushi Aggregator\\n/// @author Ilya Lyalin\\ncontract RouteProcessor5 is Ownable {\\n using SafeERC20 for IERC20;\\n using Utils for IERC20;\\n using Utils for address;\\n using SafeERC20 for IERC20Permit;\\n using InputStream for uint256;\\n\\n event Route(\\n address indexed from, \\n address to, \\n address indexed tokenIn, \\n address indexed tokenOut, \\n uint256 amountIn, \\n uint256 amountOutMin,\\n uint256 amountOut\\n );\\n\\n error MinimalOutputBalanceViolation(uint256 amountOut);\\n\\n IBentoBoxMinimal public immutable bentoBox;\\n mapping (address => bool) public priviledgedUsers;\\n address private lastCalledPool;\\n\\n uint8 private unlocked = NOT_LOCKED;\\n uint8 private paused = NOT_PAUSED;\\n modifier lock() {\\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\\n unlocked = LOCKED;\\n _;\\n unlocked = NOT_LOCKED;\\n }\\n\\n modifier onlyOwnerOrPriviledgedUser() {\\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \\\"RP: caller is not the owner or a privileged user\\\");\\n _;\\n }\\n\\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\\n bentoBox = IBentoBoxMinimal(_bentoBox);\\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n\\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\\n priviledgedUsers[priviledgedUserList[i]] = true;\\n }\\n }\\n\\n function setPriviledge(address user, bool priviledge) external onlyOwner {\\n priviledgedUsers[user] = priviledge;\\n }\\n\\n function pause() external onlyOwnerOrPriviledgedUser {\\n paused = PAUSED;\\n }\\n\\n function resume() external onlyOwnerOrPriviledgedUser {\\n paused = NOT_PAUSED;\\n }\\n\\n /// @notice For native unwrapping\\n receive() external payable {}\\n\\n /// @notice Processes the route generated off-chain. Has a lock\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @param to Where to transfer output tokens\\n /// @param route Route to process\\n /// @return amountOut Actual amount of the output token\\n function processRoute(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function transferValueAndprocessRoute(\\n address transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n transferValueTo.transferNative(amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value of input tokens to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueInput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n \\n /// @notice processes the route and sends amount of output token to \\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueOutput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\\n }\\n\\n /// @notice Processes the route generated off-chain\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteInternal(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) private returns (uint256 amountOut) {\\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\\n\\n uint256 realAmountIn = amountIn;\\n {\\n uint256 step = 0;\\n uint256 stream = InputStream.createStream(route);\\n while (stream.isNotEmpty()) {\\n uint8 commandCode = stream.readUint8();\\n if (commandCode == 1) {\\n uint256 usedAmount = processMyERC20(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 2) processUserERC20(stream, amountIn);\\n else if (commandCode == 3) {\\n uint256 usedAmount = processNative(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 4) processOnePool(stream);\\n else if (commandCode == 5) processInsideBento(stream);\\n else if (commandCode == 6) applyPermit(tokenIn, stream);\\n else revert('RouteProcessor: Unknown command code');\\n ++step;\\n }\\n }\\n\\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\\n if (tokenIn != Utils.NATIVE_ADDRESS)\\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\\n \\n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\\n\\n amountOut = balanceOutFinal - balanceOutInitial;\\n\\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\\n }\\n\\n /// @notice Applies ERC-2612 permit\\n /// @param tokenIn permitted token\\n /// @param stream Streamed program\\n function applyPermit(address tokenIn, uint256 stream) private {\\n uint256 value = stream.readUint();\\n uint256 deadline = stream.readUint();\\n uint8 v = stream.readUint8();\\n bytes32 r = stream.readBytes32();\\n bytes32 s = stream.readBytes32();\\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\\n }\\n }\\n\\n /// @notice Processes native coin: call swap for all pools that swap from native coin\\n /// @param stream Streamed program\\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\\n amountTotal = address(this).balance;\\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token from this contract balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\\n address token = stream.readAddress();\\n amountTotal = IERC20(token).balanceOf(address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n \\n /// @notice Processes ERC20 token from msg.sender balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n /// @param amountTotal Amount of tokens to take from msg.sender\\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\\n address token = stream.readAddress();\\n distributeAndSwap(stream, msg.sender, token, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token for cases when the token has only one output pool\\n /// @notice In this case liquidity is already at pool balance. This is an optimization\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processOnePool(uint256 stream) private {\\n address token = stream.readAddress();\\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\\n }\\n\\n /// @notice Processes Bento tokens \\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processInsideBento(uint256 stream) private {\\n address token = stream.readAddress();\\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n\\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountTotal Total amount of tokenIn for swaps \\n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\\n uint8 num = stream.readUint8();\\n unchecked {\\n for (uint256 i = 0; i < num; ++i) {\\n uint16 share = stream.readUint16();\\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\\n amountTotal -= amount;\\n swap(stream, from, tokenIn, amount);\\n }\\n }\\n }\\n\\n /// @notice Makes swap\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 poolType = stream.readUint8();\\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\\n else revert('RouteProcessor: Unknown pool type');\\n }\\n\\n /// @notice Wraps/unwraps native token\\n /// @param stream [direction & fake, recipient, wrapToken?]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 directionAndFake = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (directionAndFake & 1 == 1) { // wrap native\\n address wrapToken = stream.readAddress();\\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\\n } else { // unwrap native\\n if (directionAndFake & 2 == 0) {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IWETH(tokenIn).withdraw(amountIn);\\n }\\n to.transferNative(amountIn);\\n }\\n }\\n\\n /// @notice Bridge/unbridge tokens to/from Bento\\n /// @param stream [direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (direction > 0) { // outside to Bento\\n // deposit to arbitrary recipient is possible only from address(bentoBox)\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\\n else {\\n // tokens already are at address(bentoBox)\\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\\n bentoBox.strategyData(tokenIn).balance -\\n bentoBox.totals(tokenIn).elastic;\\n }\\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\\n } else { // Bento to outside\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\\n }\\n }\\n\\n /// @notice UniswapV2 pool swap\\n /// @param stream [pool, direction, recipient, fee]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\\n\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\\n\\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\\n\\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\\n }\\n\\n /// @notice Trident pool swap\\n /// @param stream [pool, swapData]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bytes memory swapData = stream.readBytes();\\n\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, pool, amountIn);\\n }\\n \\n IPool(pool).swap(swapData);\\n }\\n\\n /// @notice UniswapV3 pool swap\\n /// @param stream [pool, direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bool zeroForOne = stream.readUint8() > 0;\\n address recipient = stream.readAddress();\\n\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\\n\\n lastCalledPool = pool;\\n IUniswapV3Pool(pool).swap(\\n recipient,\\n zeroForOne,\\n int256(amountIn),\\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\\n abi.encode(tokenIn)\\n );\\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) public {\\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\\n \\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n (address tokenIn) = abi.decode(data, (address));\\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\\n function algebraSwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\\n function pancakeV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 poolType = stream.readUint8();\\n int128 fromIndex = int8(stream.readUint8());\\n int128 toIndex = int8(stream.readUint8());\\n address to = stream.readAddress();\\n address tokenOut = stream.readAddress();\\n\\n uint256 amountOut;\\n if (tokenIn == Utils.NATIVE_ADDRESS) {\\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\\n } else {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IERC20(tokenIn).approveSafe(pool, amountIn);\\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n else {\\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\\n amountOut = balanceAfter - balanceBefore;\\n }\\n }\\n\\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\\n }\\n}\\n\",\"keccak256\":\"0xcd53a7f473f1847d44c42777a194203cbff02b8c761cb2935402401f57c918a2\",\"license\":\"UNLICENSED\"},\"contracts/Utils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\n\\nlibrary Utils {\\n using SafeERC20 for IERC20;\\n\\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n /**\\n * @dev returns user's balance of token (or native)\\n */\\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\\n if (token == NATIVE_ADDRESS) return address(user).balance;\\n else return IERC20(token).balanceOf(user);\\n }\\n\\n /**\\n * @dev transfers native with correct revert bubble up\\n */\\n function transferNative(address to, uint256 amount) internal {\\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\\n if (!success) {\\n assembly {\\n revert(add(32, returnBytes), mload(returnBytes))\\n }\\n }\\n }\\n\\n /**\\n * @dev transfers ERC20 or native\\n */\\n function transferAny(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\\n else IERC20(token).safeTransfer(to, amount);\\n }\\n\\n /**\\n * @dev transfers from ERC20 or transfers native\\n */\\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n (bool success, bytes memory data) = address(token).call(\\n abi.encodeWithSelector(token.approve.selector, spender, amount)\\n );\\n return success && (data.length == 0 || abi.decode(data, (bool)));\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \\n * current allowance are not zero simultaniously (USDT for example). \\n * In second case it tries to set allowance to 0, and then back to amount.\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n return approveStable(token, spender, amount) \\n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\\n }\\n}\\n\",\"keccak256\":\"0x8c8439edc00b403abd3f34be75a06b1fe71152644ae9f19488af596bbc534ffe\",\"license\":\"UNLICENSED\"},\"interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\nstruct StrategyData {\\n uint64 strategyStartDate;\\n uint64 targetPercentage;\\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n function strategyData(address token) external view returns (StrategyData memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0x0c12eba7a5b9d22d37ab8883fe22d6a312a90682809dbd11c43f8e6ceaff73bf\",\"license\":\"UNLICENSED\"},\"interfaces/ICurve.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\ninterface ICurve {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\\n}\\n\\ninterface ICurveLegacy {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\\n}\\n\\n\",\"keccak256\":\"0x3d4940b3583e06dde20f12e92d2f6ac573b3f64bdaa1e8f480656a3763852518\",\"license\":\"UNLICENSED\"},\"interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/ITridentCLPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface ITridentCLPool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bool unwrapBento,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x572376b80c86a94692b0e27e6e63790b763295e32ba1f956c1d331fc1296de8d\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IUniswapV2Pair.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Pair {\\n event Approval(address indexed owner, address indexed spender, uint value);\\n event Transfer(address indexed from, address indexed to, uint value);\\n\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function allowance(address owner, address spender) external view returns (uint);\\n\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address to, uint value) external returns (bool);\\n function transferFrom(address from, address to, uint value) external returns (bool);\\n\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n function nonces(address owner) external view returns (uint);\\n\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n event Mint(address indexed sender, uint amount0, uint amount1);\\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\\n event Swap(\\n address indexed sender,\\n uint amount0In,\\n uint amount1In,\\n uint amount0Out,\\n uint amount1Out,\\n address indexed to\\n );\\n event Sync(uint112 reserve0, uint112 reserve1);\\n\\n function MINIMUM_LIQUIDITY() external pure returns (uint);\\n function factory() external view returns (address);\\n function token0() external view returns (address);\\n function token1() external view returns (address);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\\n function price0CumulativeLast() external view returns (uint);\\n function price1CumulativeLast() external view returns (uint);\\n function kLast() external view returns (uint);\\n\\n function mint(address to) external returns (uint liquidity);\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function skim(address to) external;\\n function sync() external;\\n\\n function initialize(address, address) external;\\n}\",\"keccak256\":\"0x08f9a63b34855eec941be8d36a04424f1a1725a2c030373fcef3afeb480ca385\",\"license\":\"GPL-3.0\"},\"interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IUniswapV3Pool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x2a4d7c6120e613f0e95d4dc8c650efb9b59e3c25c64e3e5c0a379281500f0a79\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IWETH.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0xae8529ae159f784b90fdcd0629bd03bf7b68accc81edccac53357ad08406a378\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}", + "bytecode": "0x60a06040526002805461ffff60a01b191661010160a01b1790553480156200002657600080fd5b50604051620040a3380380620040a383398101604081905262000049916200016e565b6200005433620000eb565b6001600160a01b038216608052600280546001600160a01b031916600117905560005b8151811015620000e25760018060008484815181106200009b576200009b62000257565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000d9816200026d565b91505062000077565b50505062000297565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200015357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200018257600080fd5b6200018d836200013b565b602084810151919350906001600160401b0380821115620001ad57600080fd5b818601915086601f830112620001c257600080fd5b815181811115620001d757620001d762000158565b8060051b604051601f19603f83011681018181108582111715620001ff57620001ff62000158565b6040529182528482019250838101850191898311156200021e57600080fd5b938501935b82851015620002475762000237856200013b565b8452938501939285019262000223565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200029057634e487b7160e01b600052601160045260246000fd5b5060010190565b608051613da3620003006000396000818161018d01528181611798015281816127380152818161279d01528181612807015281816128cc0152818161297901528181612a5d01528181612b6401528181612c1001528181612cdf0152612df10152613da36000f3fe6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "deployedBytecode": "0x6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "devdoc": { + "author": "Ilya Lyalin", + "kind": "dev", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IAlgebraPoolActions#swap call" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the PancakeV3Pool#swap call" + } + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "route": "Route to process", + "to": "Where to transfer output tokens", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IUniswapV3PoolActions#swap call" + } + } + }, + "title": "A route processor for the Sushi Aggregator", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IAlgebraPool#swap." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via PancakeV3Pool#swap." + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "notice": "Processes the route generated off-chain. Has a lock" + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value of input tokens to and then processes the route" + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "processes the route and sends amount of output token to " + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value to and then processes the route" + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 1060, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "priviledgedUsers", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 1062, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "lastCalledPool", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 1065, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "unlocked", + "offset": 20, + "slot": "2", + "type": "t_uint8" + }, + { + "astId": 1068, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "paused", + "offset": 21, + "slot": "2", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/scroll/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json b/protocols/route-processor/deployments/scroll/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json new file mode 100644 index 0000000000..01826e7b93 --- /dev/null +++ b/protocols/route-processor/deployments/scroll/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json @@ -0,0 +1,80 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" + }, + "contracts/InputStream.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" + }, + "contracts/RouteProcessor5.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" + }, + "contracts/Utils.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "interfaces/IBentoBoxMinimal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" + }, + "interfaces/ICurve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" + }, + "interfaces/IPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" + }, + "interfaces/ITridentCLPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/sepolia/.chainId b/protocols/route-processor/deployments/sepolia/.chainId new file mode 100644 index 0000000000..bd8d1cd44c --- /dev/null +++ b/protocols/route-processor/deployments/sepolia/.chainId @@ -0,0 +1 @@ +11155111 \ No newline at end of file diff --git a/protocols/route-processor/deployments/sepolia/RouteProcessor5.json b/protocols/route-processor/deployments/sepolia/RouteProcessor5.json new file mode 100644 index 0000000000..4bd6525690 --- /dev/null +++ b/protocols/route-processor/deployments/sepolia/RouteProcessor5.json @@ -0,0 +1,704 @@ +{ + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_bentoBox", + "type": "address" + }, + { + "internalType": "address[]", + "name": "priviledgedUserList", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "MinimalOutputBalanceViolation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Route", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "algebraSwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bentoBox", + "outputs": [ + { + "internalType": "contract IBentoBoxMinimal", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "pancakeV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "priviledgedUsers", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueInput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "priviledge", + "type": "bool" + } + ], + "name": "setPriviledge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "transferValueAndprocessRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0xf8bb1f576ee578ec5979ce2f7b8f5f4ee8ae5e107f0aeef7cc4e27f732bea053", + "receipt": { + "to": null, + "from": "0x282607716D9B4fDD0B094d5864fac56313f5e665", + "contractAddress": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "transactionIndex": 87, + "gasUsed": "3489875", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000020000000000000000000000000000000000000001000000000000000000000000000000000000000000040000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000000000000000000000000000", + "blockHash": "0x94a4f7db64fc9811a51af0565b9eb342bd4d657eb265c35566669fa7583a1847", + "transactionHash": "0xf8bb1f576ee578ec5979ce2f7b8f5f4ee8ae5e107f0aeef7cc4e27f732bea053", + "logs": [ + { + "transactionIndex": 87, + "blockNumber": 6399010, + "transactionHash": "0xf8bb1f576ee578ec5979ce2f7b8f5f4ee8ae5e107f0aeef7cc4e27f732bea053", + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000282607716d9b4fdd0b094d5864fac56313f5e665" + ], + "data": "0x", + "logIndex": 145, + "blockHash": "0x94a4f7db64fc9811a51af0565b9eb342bd4d657eb265c35566669fa7583a1847" + } + ], + "blockNumber": 6399010, + "cumulativeGasUsed": "17852805", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000000", + [] + ], + "numDeployments": 1, + "solcInputHash": "e556d43a3caf4f1fb4f12d632d103b28", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bentoBox\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"priviledgedUserList\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"MinimalOutputBalanceViolation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"Route\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"algebraSwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"pancakeV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"priviledgedUsers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"priviledge\",\"type\":\"bool\"}],\"name\":\"setPriviledge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"transferValueAndprocessRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"Ilya Lyalin\",\"kind\":\"dev\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IAlgebraPoolActions#swap call\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the PancakeV3Pool#swap call\"}},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"route\":\"Route to process\",\"to\":\"Where to transfer output tokens\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IUniswapV3PoolActions#swap call\"}}},\"title\":\"A route processor for the Sushi Aggregator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\"},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Processes the route generated off-chain. Has a lock\"},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value of input tokens to and then processes the route\"},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"processes the route and sends amount of output token to \"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value to and then processes the route\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RouteProcessor5.sol\":\"RouteProcessor5\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\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 Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.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 function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\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\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\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 * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\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\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/InputStream.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\n/** @notice Simple read stream */\\nlibrary InputStream {\\n\\n /** @notice Creates stream from data\\n * @param data data\\n */\\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\\n assembly {\\n stream := mload(0x40)\\n mstore(0x40, add(stream, 64))\\n mstore(stream, data)\\n let length := mload(data)\\n mstore(add(stream, 32), add(data, length))\\n }\\n }\\n\\n /** @notice Checks if stream is not empty\\n * @param stream stream\\n */\\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\\n uint256 pos;\\n uint256 finish;\\n assembly {\\n pos := mload(stream)\\n finish := mload(add(stream, 32))\\n }\\n return pos < finish;\\n }\\n\\n /** @notice Reads uint8 from the stream\\n * @param stream stream\\n */\\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 1)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint16 from the stream\\n * @param stream stream\\n */\\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 2)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint24 from the stream\\n * @param stream stream\\n */\\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 3)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint32 from the stream\\n * @param stream stream\\n */\\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 4)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint256 from the stream\\n * @param stream stream\\n */\\n function readUint(uint256 stream) internal pure returns (uint256 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes32 from the stream\\n * @param stream stream\\n */\\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads address from the stream\\n * @param stream stream\\n */\\n function readAddress(uint256 stream) internal pure returns (address res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 20)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes from the stream\\n * @param stream stream\\n */\\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\\n assembly {\\n let pos := mload(stream)\\n res := add(pos, 32)\\n let length := mload(res)\\n mstore(stream, add(res, length))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x24e24bd0e49cbddacbf3b26bcd4bdffac63d11f3259bc05bc93c0835e8ff5300\",\"license\":\"UNLICENSED\"},\"contracts/RouteProcessor5.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '../interfaces/IUniswapV2Pair.sol';\\nimport '../interfaces/IUniswapV3Pool.sol';\\nimport '../interfaces/ITridentCLPool.sol';\\nimport '../interfaces/IBentoBoxMinimal.sol';\\nimport '../interfaces/IPool.sol';\\nimport '../interfaces/IWETH.sol';\\nimport '../interfaces/ICurve.sol';\\nimport './InputStream.sol';\\nimport './Utils.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\\n\\nuint8 constant LOCKED = 2;\\nuint8 constant NOT_LOCKED = 1;\\nuint8 constant PAUSED = 2;\\nuint8 constant NOT_PAUSED = 1;\\n\\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\nuint160 constant MIN_SQRT_RATIO = 4295128739;\\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n/// @title A route processor for the Sushi Aggregator\\n/// @author Ilya Lyalin\\ncontract RouteProcessor5 is Ownable {\\n using SafeERC20 for IERC20;\\n using Utils for IERC20;\\n using Utils for address;\\n using SafeERC20 for IERC20Permit;\\n using InputStream for uint256;\\n\\n event Route(\\n address indexed from, \\n address to, \\n address indexed tokenIn, \\n address indexed tokenOut, \\n uint256 amountIn, \\n uint256 amountOutMin,\\n uint256 amountOut\\n );\\n\\n error MinimalOutputBalanceViolation(uint256 amountOut);\\n\\n IBentoBoxMinimal public immutable bentoBox;\\n mapping (address => bool) public priviledgedUsers;\\n address private lastCalledPool;\\n\\n uint8 private unlocked = NOT_LOCKED;\\n uint8 private paused = NOT_PAUSED;\\n modifier lock() {\\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\\n unlocked = LOCKED;\\n _;\\n unlocked = NOT_LOCKED;\\n }\\n\\n modifier onlyOwnerOrPriviledgedUser() {\\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \\\"RP: caller is not the owner or a privileged user\\\");\\n _;\\n }\\n\\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\\n bentoBox = IBentoBoxMinimal(_bentoBox);\\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n\\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\\n priviledgedUsers[priviledgedUserList[i]] = true;\\n }\\n }\\n\\n function setPriviledge(address user, bool priviledge) external onlyOwner {\\n priviledgedUsers[user] = priviledge;\\n }\\n\\n function pause() external onlyOwnerOrPriviledgedUser {\\n paused = PAUSED;\\n }\\n\\n function resume() external onlyOwnerOrPriviledgedUser {\\n paused = NOT_PAUSED;\\n }\\n\\n /// @notice For native unwrapping\\n receive() external payable {}\\n\\n /// @notice Processes the route generated off-chain. Has a lock\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @param to Where to transfer output tokens\\n /// @param route Route to process\\n /// @return amountOut Actual amount of the output token\\n function processRoute(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function transferValueAndprocessRoute(\\n address transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n transferValueTo.transferNative(amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value of input tokens to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueInput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n \\n /// @notice processes the route and sends amount of output token to \\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueOutput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\\n }\\n\\n /// @notice Processes the route generated off-chain\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteInternal(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) private returns (uint256 amountOut) {\\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\\n\\n uint256 realAmountIn = amountIn;\\n {\\n uint256 step = 0;\\n uint256 stream = InputStream.createStream(route);\\n while (stream.isNotEmpty()) {\\n uint8 commandCode = stream.readUint8();\\n if (commandCode == 1) {\\n uint256 usedAmount = processMyERC20(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 2) processUserERC20(stream, amountIn);\\n else if (commandCode == 3) {\\n uint256 usedAmount = processNative(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 4) processOnePool(stream);\\n else if (commandCode == 5) processInsideBento(stream);\\n else if (commandCode == 6) applyPermit(tokenIn, stream);\\n else revert('RouteProcessor: Unknown command code');\\n ++step;\\n }\\n }\\n\\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\\n if (tokenIn != Utils.NATIVE_ADDRESS)\\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\\n \\n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\\n\\n amountOut = balanceOutFinal - balanceOutInitial;\\n\\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\\n }\\n\\n /// @notice Applies ERC-2612 permit\\n /// @param tokenIn permitted token\\n /// @param stream Streamed program\\n function applyPermit(address tokenIn, uint256 stream) private {\\n uint256 value = stream.readUint();\\n uint256 deadline = stream.readUint();\\n uint8 v = stream.readUint8();\\n bytes32 r = stream.readBytes32();\\n bytes32 s = stream.readBytes32();\\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\\n }\\n }\\n\\n /// @notice Processes native coin: call swap for all pools that swap from native coin\\n /// @param stream Streamed program\\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\\n amountTotal = address(this).balance;\\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token from this contract balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\\n address token = stream.readAddress();\\n amountTotal = IERC20(token).balanceOf(address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n \\n /// @notice Processes ERC20 token from msg.sender balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n /// @param amountTotal Amount of tokens to take from msg.sender\\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\\n address token = stream.readAddress();\\n distributeAndSwap(stream, msg.sender, token, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token for cases when the token has only one output pool\\n /// @notice In this case liquidity is already at pool balance. This is an optimization\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processOnePool(uint256 stream) private {\\n address token = stream.readAddress();\\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\\n }\\n\\n /// @notice Processes Bento tokens \\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processInsideBento(uint256 stream) private {\\n address token = stream.readAddress();\\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n\\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountTotal Total amount of tokenIn for swaps \\n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\\n uint8 num = stream.readUint8();\\n unchecked {\\n for (uint256 i = 0; i < num; ++i) {\\n uint16 share = stream.readUint16();\\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\\n amountTotal -= amount;\\n swap(stream, from, tokenIn, amount);\\n }\\n }\\n }\\n\\n /// @notice Makes swap\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 poolType = stream.readUint8();\\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\\n else revert('RouteProcessor: Unknown pool type');\\n }\\n\\n /// @notice Wraps/unwraps native token\\n /// @param stream [direction & fake, recipient, wrapToken?]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 directionAndFake = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (directionAndFake & 1 == 1) { // wrap native\\n address wrapToken = stream.readAddress();\\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\\n } else { // unwrap native\\n if (directionAndFake & 2 == 0) {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IWETH(tokenIn).withdraw(amountIn);\\n }\\n to.transferNative(amountIn);\\n }\\n }\\n\\n /// @notice Bridge/unbridge tokens to/from Bento\\n /// @param stream [direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (direction > 0) { // outside to Bento\\n // deposit to arbitrary recipient is possible only from address(bentoBox)\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\\n else {\\n // tokens already are at address(bentoBox)\\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\\n bentoBox.strategyData(tokenIn).balance -\\n bentoBox.totals(tokenIn).elastic;\\n }\\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\\n } else { // Bento to outside\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\\n }\\n }\\n\\n /// @notice UniswapV2 pool swap\\n /// @param stream [pool, direction, recipient, fee]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\\n\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\\n\\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\\n\\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\\n }\\n\\n /// @notice Trident pool swap\\n /// @param stream [pool, swapData]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bytes memory swapData = stream.readBytes();\\n\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, pool, amountIn);\\n }\\n \\n IPool(pool).swap(swapData);\\n }\\n\\n /// @notice UniswapV3 pool swap\\n /// @param stream [pool, direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bool zeroForOne = stream.readUint8() > 0;\\n address recipient = stream.readAddress();\\n\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\\n\\n lastCalledPool = pool;\\n IUniswapV3Pool(pool).swap(\\n recipient,\\n zeroForOne,\\n int256(amountIn),\\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\\n abi.encode(tokenIn)\\n );\\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) public {\\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\\n \\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n (address tokenIn) = abi.decode(data, (address));\\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\\n function algebraSwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\\n function pancakeV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 poolType = stream.readUint8();\\n int128 fromIndex = int8(stream.readUint8());\\n int128 toIndex = int8(stream.readUint8());\\n address to = stream.readAddress();\\n address tokenOut = stream.readAddress();\\n\\n uint256 amountOut;\\n if (tokenIn == Utils.NATIVE_ADDRESS) {\\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\\n } else {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IERC20(tokenIn).approveSafe(pool, amountIn);\\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n else {\\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\\n amountOut = balanceAfter - balanceBefore;\\n }\\n }\\n\\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\\n }\\n}\\n\",\"keccak256\":\"0xcd53a7f473f1847d44c42777a194203cbff02b8c761cb2935402401f57c918a2\",\"license\":\"UNLICENSED\"},\"contracts/Utils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\n\\nlibrary Utils {\\n using SafeERC20 for IERC20;\\n\\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n /**\\n * @dev returns user's balance of token (or native)\\n */\\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\\n if (token == NATIVE_ADDRESS) return address(user).balance;\\n else return IERC20(token).balanceOf(user);\\n }\\n\\n /**\\n * @dev transfers native with correct revert bubble up\\n */\\n function transferNative(address to, uint256 amount) internal {\\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\\n if (!success) {\\n assembly {\\n revert(add(32, returnBytes), mload(returnBytes))\\n }\\n }\\n }\\n\\n /**\\n * @dev transfers ERC20 or native\\n */\\n function transferAny(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\\n else IERC20(token).safeTransfer(to, amount);\\n }\\n\\n /**\\n * @dev transfers from ERC20 or transfers native\\n */\\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n (bool success, bytes memory data) = address(token).call(\\n abi.encodeWithSelector(token.approve.selector, spender, amount)\\n );\\n return success && (data.length == 0 || abi.decode(data, (bool)));\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \\n * current allowance are not zero simultaniously (USDT for example). \\n * In second case it tries to set allowance to 0, and then back to amount.\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n return approveStable(token, spender, amount) \\n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\\n }\\n}\\n\",\"keccak256\":\"0x8c8439edc00b403abd3f34be75a06b1fe71152644ae9f19488af596bbc534ffe\",\"license\":\"UNLICENSED\"},\"interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\nstruct StrategyData {\\n uint64 strategyStartDate;\\n uint64 targetPercentage;\\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n function strategyData(address token) external view returns (StrategyData memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0x0c12eba7a5b9d22d37ab8883fe22d6a312a90682809dbd11c43f8e6ceaff73bf\",\"license\":\"UNLICENSED\"},\"interfaces/ICurve.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\ninterface ICurve {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\\n}\\n\\ninterface ICurveLegacy {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\\n}\\n\\n\",\"keccak256\":\"0x3d4940b3583e06dde20f12e92d2f6ac573b3f64bdaa1e8f480656a3763852518\",\"license\":\"UNLICENSED\"},\"interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/ITridentCLPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface ITridentCLPool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bool unwrapBento,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x572376b80c86a94692b0e27e6e63790b763295e32ba1f956c1d331fc1296de8d\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IUniswapV2Pair.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Pair {\\n event Approval(address indexed owner, address indexed spender, uint value);\\n event Transfer(address indexed from, address indexed to, uint value);\\n\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function allowance(address owner, address spender) external view returns (uint);\\n\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address to, uint value) external returns (bool);\\n function transferFrom(address from, address to, uint value) external returns (bool);\\n\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n function nonces(address owner) external view returns (uint);\\n\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n event Mint(address indexed sender, uint amount0, uint amount1);\\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\\n event Swap(\\n address indexed sender,\\n uint amount0In,\\n uint amount1In,\\n uint amount0Out,\\n uint amount1Out,\\n address indexed to\\n );\\n event Sync(uint112 reserve0, uint112 reserve1);\\n\\n function MINIMUM_LIQUIDITY() external pure returns (uint);\\n function factory() external view returns (address);\\n function token0() external view returns (address);\\n function token1() external view returns (address);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\\n function price0CumulativeLast() external view returns (uint);\\n function price1CumulativeLast() external view returns (uint);\\n function kLast() external view returns (uint);\\n\\n function mint(address to) external returns (uint liquidity);\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function skim(address to) external;\\n function sync() external;\\n\\n function initialize(address, address) external;\\n}\",\"keccak256\":\"0x08f9a63b34855eec941be8d36a04424f1a1725a2c030373fcef3afeb480ca385\",\"license\":\"GPL-3.0\"},\"interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IUniswapV3Pool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x2a4d7c6120e613f0e95d4dc8c650efb9b59e3c25c64e3e5c0a379281500f0a79\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IWETH.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0xae8529ae159f784b90fdcd0629bd03bf7b68accc81edccac53357ad08406a378\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}", + "bytecode": "0x60a06040526002805461ffff60a01b191661010160a01b1790553480156200002657600080fd5b50604051620040a3380380620040a383398101604081905262000049916200016e565b6200005433620000eb565b6001600160a01b038216608052600280546001600160a01b031916600117905560005b8151811015620000e25760018060008484815181106200009b576200009b62000257565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000d9816200026d565b91505062000077565b50505062000297565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200015357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200018257600080fd5b6200018d836200013b565b602084810151919350906001600160401b0380821115620001ad57600080fd5b818601915086601f830112620001c257600080fd5b815181811115620001d757620001d762000158565b8060051b604051601f19603f83011681018181108582111715620001ff57620001ff62000158565b6040529182528482019250838101850191898311156200021e57600080fd5b938501935b82851015620002475762000237856200013b565b8452938501939285019262000223565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200029057634e487b7160e01b600052601160045260246000fd5b5060010190565b608051613da3620003006000396000818161018d01528181611798015281816127380152818161279d01528181612807015281816128cc0152818161297901528181612a5d01528181612b6401528181612c1001528181612cdf0152612df10152613da36000f3fe6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "deployedBytecode": "0x6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "devdoc": { + "author": "Ilya Lyalin", + "kind": "dev", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IAlgebraPoolActions#swap call" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the PancakeV3Pool#swap call" + } + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "route": "Route to process", + "to": "Where to transfer output tokens", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IUniswapV3PoolActions#swap call" + } + } + }, + "title": "A route processor for the Sushi Aggregator", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IAlgebraPool#swap." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via PancakeV3Pool#swap." + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "notice": "Processes the route generated off-chain. Has a lock" + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value of input tokens to and then processes the route" + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "processes the route and sends amount of output token to " + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value to and then processes the route" + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 1060, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "priviledgedUsers", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 1062, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "lastCalledPool", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 1065, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "unlocked", + "offset": 20, + "slot": "2", + "type": "t_uint8" + }, + { + "astId": 1068, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "paused", + "offset": 21, + "slot": "2", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/sepolia/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json b/protocols/route-processor/deployments/sepolia/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json new file mode 100644 index 0000000000..01826e7b93 --- /dev/null +++ b/protocols/route-processor/deployments/sepolia/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json @@ -0,0 +1,80 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" + }, + "contracts/InputStream.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" + }, + "contracts/RouteProcessor5.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" + }, + "contracts/Utils.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "interfaces/IBentoBoxMinimal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" + }, + "interfaces/ICurve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" + }, + "interfaces/IPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" + }, + "interfaces/ITridentCLPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/skale-europa/RouteProcessor5.json b/protocols/route-processor/deployments/skale-europa/RouteProcessor5.json new file mode 100644 index 0000000000..28c139c06f --- /dev/null +++ b/protocols/route-processor/deployments/skale-europa/RouteProcessor5.json @@ -0,0 +1,704 @@ +{ + "address": "0xd40535cF25cD9E8Ed5E7Ee57534F534F6fCc95b1", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_bentoBox", + "type": "address" + }, + { + "internalType": "address[]", + "name": "priviledgedUserList", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "MinimalOutputBalanceViolation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Route", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "algebraSwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bentoBox", + "outputs": [ + { + "internalType": "contract IBentoBoxMinimal", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "pancakeV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "priviledgedUsers", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueInput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "priviledge", + "type": "bool" + } + ], + "name": "setPriviledge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "transferValueAndprocessRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0xa71d0378be1797e89efa438cdce7c99a60e4eaa4daf9c28944f6334ec3a59caa", + "receipt": { + "to": "0x0000000000000000000000000000000000000000", + "from": "0x19f012FB3A5610B076b4Db95d1EE4E3dC3AA5A9C", + "contractAddress": "0xd40535cF25cD9E8Ed5E7Ee57534F534F6fCc95b1", + "transactionIndex": 0, + "gasUsed": "3491833", + "logsBloom": "0x00000000200000000000000000000000000000000008000000800000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000004000400000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x30466f4f115b0fbeb812313f9b4bec9ada070ecd2f6aa6a24dda9e3c42f7b0ed", + "transactionHash": "0xa71d0378be1797e89efa438cdce7c99a60e4eaa4daf9c28944f6334ec3a59caa", + "logs": [ + { + "transactionIndex": 0, + "blockNumber": 6013321, + "transactionHash": "0xa71d0378be1797e89efa438cdce7c99a60e4eaa4daf9c28944f6334ec3a59caa", + "address": "0xd40535cF25cD9E8Ed5E7Ee57534F534F6fCc95b1", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000019f012fb3a5610b076b4db95d1ee4e3dc3aa5a9c" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0x30466f4f115b0fbeb812313f9b4bec9ada070ecd2f6aa6a24dda9e3c42f7b0ed" + } + ], + "blockNumber": 6013321, + "cumulativeGasUsed": "3491833", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000000", + [] + ], + "numDeployments": 1, + "solcInputHash": "e556d43a3caf4f1fb4f12d632d103b28", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bentoBox\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"priviledgedUserList\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"MinimalOutputBalanceViolation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"Route\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"algebraSwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"pancakeV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"priviledgedUsers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"priviledge\",\"type\":\"bool\"}],\"name\":\"setPriviledge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"transferValueAndprocessRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"Ilya Lyalin\",\"kind\":\"dev\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IAlgebraPoolActions#swap call\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the PancakeV3Pool#swap call\"}},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"route\":\"Route to process\",\"to\":\"Where to transfer output tokens\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IUniswapV3PoolActions#swap call\"}}},\"title\":\"A route processor for the Sushi Aggregator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\"},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Processes the route generated off-chain. Has a lock\"},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value of input tokens to and then processes the route\"},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"processes the route and sends amount of output token to \"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value to and then processes the route\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RouteProcessor5.sol\":\"RouteProcessor5\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\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 Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.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 function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\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\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\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 * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\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\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/InputStream.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\n/** @notice Simple read stream */\\nlibrary InputStream {\\n\\n /** @notice Creates stream from data\\n * @param data data\\n */\\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\\n assembly {\\n stream := mload(0x40)\\n mstore(0x40, add(stream, 64))\\n mstore(stream, data)\\n let length := mload(data)\\n mstore(add(stream, 32), add(data, length))\\n }\\n }\\n\\n /** @notice Checks if stream is not empty\\n * @param stream stream\\n */\\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\\n uint256 pos;\\n uint256 finish;\\n assembly {\\n pos := mload(stream)\\n finish := mload(add(stream, 32))\\n }\\n return pos < finish;\\n }\\n\\n /** @notice Reads uint8 from the stream\\n * @param stream stream\\n */\\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 1)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint16 from the stream\\n * @param stream stream\\n */\\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 2)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint24 from the stream\\n * @param stream stream\\n */\\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 3)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint32 from the stream\\n * @param stream stream\\n */\\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 4)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint256 from the stream\\n * @param stream stream\\n */\\n function readUint(uint256 stream) internal pure returns (uint256 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes32 from the stream\\n * @param stream stream\\n */\\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads address from the stream\\n * @param stream stream\\n */\\n function readAddress(uint256 stream) internal pure returns (address res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 20)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes from the stream\\n * @param stream stream\\n */\\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\\n assembly {\\n let pos := mload(stream)\\n res := add(pos, 32)\\n let length := mload(res)\\n mstore(stream, add(res, length))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x24e24bd0e49cbddacbf3b26bcd4bdffac63d11f3259bc05bc93c0835e8ff5300\",\"license\":\"UNLICENSED\"},\"contracts/RouteProcessor5.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '../interfaces/IUniswapV2Pair.sol';\\nimport '../interfaces/IUniswapV3Pool.sol';\\nimport '../interfaces/ITridentCLPool.sol';\\nimport '../interfaces/IBentoBoxMinimal.sol';\\nimport '../interfaces/IPool.sol';\\nimport '../interfaces/IWETH.sol';\\nimport '../interfaces/ICurve.sol';\\nimport './InputStream.sol';\\nimport './Utils.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\\n\\nuint8 constant LOCKED = 2;\\nuint8 constant NOT_LOCKED = 1;\\nuint8 constant PAUSED = 2;\\nuint8 constant NOT_PAUSED = 1;\\n\\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\nuint160 constant MIN_SQRT_RATIO = 4295128739;\\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n/// @title A route processor for the Sushi Aggregator\\n/// @author Ilya Lyalin\\ncontract RouteProcessor5 is Ownable {\\n using SafeERC20 for IERC20;\\n using Utils for IERC20;\\n using Utils for address;\\n using SafeERC20 for IERC20Permit;\\n using InputStream for uint256;\\n\\n event Route(\\n address indexed from, \\n address to, \\n address indexed tokenIn, \\n address indexed tokenOut, \\n uint256 amountIn, \\n uint256 amountOutMin,\\n uint256 amountOut\\n );\\n\\n error MinimalOutputBalanceViolation(uint256 amountOut);\\n\\n IBentoBoxMinimal public immutable bentoBox;\\n mapping (address => bool) public priviledgedUsers;\\n address private lastCalledPool;\\n\\n uint8 private unlocked = NOT_LOCKED;\\n uint8 private paused = NOT_PAUSED;\\n modifier lock() {\\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\\n unlocked = LOCKED;\\n _;\\n unlocked = NOT_LOCKED;\\n }\\n\\n modifier onlyOwnerOrPriviledgedUser() {\\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \\\"RP: caller is not the owner or a privileged user\\\");\\n _;\\n }\\n\\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\\n bentoBox = IBentoBoxMinimal(_bentoBox);\\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n\\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\\n priviledgedUsers[priviledgedUserList[i]] = true;\\n }\\n }\\n\\n function setPriviledge(address user, bool priviledge) external onlyOwner {\\n priviledgedUsers[user] = priviledge;\\n }\\n\\n function pause() external onlyOwnerOrPriviledgedUser {\\n paused = PAUSED;\\n }\\n\\n function resume() external onlyOwnerOrPriviledgedUser {\\n paused = NOT_PAUSED;\\n }\\n\\n /// @notice For native unwrapping\\n receive() external payable {}\\n\\n /// @notice Processes the route generated off-chain. Has a lock\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @param to Where to transfer output tokens\\n /// @param route Route to process\\n /// @return amountOut Actual amount of the output token\\n function processRoute(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function transferValueAndprocessRoute(\\n address transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n transferValueTo.transferNative(amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value of input tokens to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueInput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n \\n /// @notice processes the route and sends amount of output token to \\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueOutput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\\n }\\n\\n /// @notice Processes the route generated off-chain\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteInternal(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) private returns (uint256 amountOut) {\\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\\n\\n uint256 realAmountIn = amountIn;\\n {\\n uint256 step = 0;\\n uint256 stream = InputStream.createStream(route);\\n while (stream.isNotEmpty()) {\\n uint8 commandCode = stream.readUint8();\\n if (commandCode == 1) {\\n uint256 usedAmount = processMyERC20(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 2) processUserERC20(stream, amountIn);\\n else if (commandCode == 3) {\\n uint256 usedAmount = processNative(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 4) processOnePool(stream);\\n else if (commandCode == 5) processInsideBento(stream);\\n else if (commandCode == 6) applyPermit(tokenIn, stream);\\n else revert('RouteProcessor: Unknown command code');\\n ++step;\\n }\\n }\\n\\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\\n if (tokenIn != Utils.NATIVE_ADDRESS)\\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\\n \\n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\\n\\n amountOut = balanceOutFinal - balanceOutInitial;\\n\\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\\n }\\n\\n /// @notice Applies ERC-2612 permit\\n /// @param tokenIn permitted token\\n /// @param stream Streamed program\\n function applyPermit(address tokenIn, uint256 stream) private {\\n uint256 value = stream.readUint();\\n uint256 deadline = stream.readUint();\\n uint8 v = stream.readUint8();\\n bytes32 r = stream.readBytes32();\\n bytes32 s = stream.readBytes32();\\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\\n }\\n }\\n\\n /// @notice Processes native coin: call swap for all pools that swap from native coin\\n /// @param stream Streamed program\\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\\n amountTotal = address(this).balance;\\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token from this contract balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\\n address token = stream.readAddress();\\n amountTotal = IERC20(token).balanceOf(address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n \\n /// @notice Processes ERC20 token from msg.sender balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n /// @param amountTotal Amount of tokens to take from msg.sender\\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\\n address token = stream.readAddress();\\n distributeAndSwap(stream, msg.sender, token, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token for cases when the token has only one output pool\\n /// @notice In this case liquidity is already at pool balance. This is an optimization\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processOnePool(uint256 stream) private {\\n address token = stream.readAddress();\\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\\n }\\n\\n /// @notice Processes Bento tokens \\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processInsideBento(uint256 stream) private {\\n address token = stream.readAddress();\\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n\\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountTotal Total amount of tokenIn for swaps \\n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\\n uint8 num = stream.readUint8();\\n unchecked {\\n for (uint256 i = 0; i < num; ++i) {\\n uint16 share = stream.readUint16();\\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\\n amountTotal -= amount;\\n swap(stream, from, tokenIn, amount);\\n }\\n }\\n }\\n\\n /// @notice Makes swap\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 poolType = stream.readUint8();\\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\\n else revert('RouteProcessor: Unknown pool type');\\n }\\n\\n /// @notice Wraps/unwraps native token\\n /// @param stream [direction & fake, recipient, wrapToken?]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 directionAndFake = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (directionAndFake & 1 == 1) { // wrap native\\n address wrapToken = stream.readAddress();\\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\\n } else { // unwrap native\\n if (directionAndFake & 2 == 0) {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IWETH(tokenIn).withdraw(amountIn);\\n }\\n to.transferNative(amountIn);\\n }\\n }\\n\\n /// @notice Bridge/unbridge tokens to/from Bento\\n /// @param stream [direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (direction > 0) { // outside to Bento\\n // deposit to arbitrary recipient is possible only from address(bentoBox)\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\\n else {\\n // tokens already are at address(bentoBox)\\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\\n bentoBox.strategyData(tokenIn).balance -\\n bentoBox.totals(tokenIn).elastic;\\n }\\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\\n } else { // Bento to outside\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\\n }\\n }\\n\\n /// @notice UniswapV2 pool swap\\n /// @param stream [pool, direction, recipient, fee]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\\n\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\\n\\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\\n\\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\\n }\\n\\n /// @notice Trident pool swap\\n /// @param stream [pool, swapData]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bytes memory swapData = stream.readBytes();\\n\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, pool, amountIn);\\n }\\n \\n IPool(pool).swap(swapData);\\n }\\n\\n /// @notice UniswapV3 pool swap\\n /// @param stream [pool, direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bool zeroForOne = stream.readUint8() > 0;\\n address recipient = stream.readAddress();\\n\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\\n\\n lastCalledPool = pool;\\n IUniswapV3Pool(pool).swap(\\n recipient,\\n zeroForOne,\\n int256(amountIn),\\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\\n abi.encode(tokenIn)\\n );\\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) public {\\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\\n \\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n (address tokenIn) = abi.decode(data, (address));\\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\\n function algebraSwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\\n function pancakeV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 poolType = stream.readUint8();\\n int128 fromIndex = int8(stream.readUint8());\\n int128 toIndex = int8(stream.readUint8());\\n address to = stream.readAddress();\\n address tokenOut = stream.readAddress();\\n\\n uint256 amountOut;\\n if (tokenIn == Utils.NATIVE_ADDRESS) {\\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\\n } else {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IERC20(tokenIn).approveSafe(pool, amountIn);\\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n else {\\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\\n amountOut = balanceAfter - balanceBefore;\\n }\\n }\\n\\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\\n }\\n}\\n\",\"keccak256\":\"0xcd53a7f473f1847d44c42777a194203cbff02b8c761cb2935402401f57c918a2\",\"license\":\"UNLICENSED\"},\"contracts/Utils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\n\\nlibrary Utils {\\n using SafeERC20 for IERC20;\\n\\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n /**\\n * @dev returns user's balance of token (or native)\\n */\\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\\n if (token == NATIVE_ADDRESS) return address(user).balance;\\n else return IERC20(token).balanceOf(user);\\n }\\n\\n /**\\n * @dev transfers native with correct revert bubble up\\n */\\n function transferNative(address to, uint256 amount) internal {\\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\\n if (!success) {\\n assembly {\\n revert(add(32, returnBytes), mload(returnBytes))\\n }\\n }\\n }\\n\\n /**\\n * @dev transfers ERC20 or native\\n */\\n function transferAny(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\\n else IERC20(token).safeTransfer(to, amount);\\n }\\n\\n /**\\n * @dev transfers from ERC20 or transfers native\\n */\\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n (bool success, bytes memory data) = address(token).call(\\n abi.encodeWithSelector(token.approve.selector, spender, amount)\\n );\\n return success && (data.length == 0 || abi.decode(data, (bool)));\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \\n * current allowance are not zero simultaniously (USDT for example). \\n * In second case it tries to set allowance to 0, and then back to amount.\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n return approveStable(token, spender, amount) \\n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\\n }\\n}\\n\",\"keccak256\":\"0x8c8439edc00b403abd3f34be75a06b1fe71152644ae9f19488af596bbc534ffe\",\"license\":\"UNLICENSED\"},\"interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\nstruct StrategyData {\\n uint64 strategyStartDate;\\n uint64 targetPercentage;\\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n function strategyData(address token) external view returns (StrategyData memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0x0c12eba7a5b9d22d37ab8883fe22d6a312a90682809dbd11c43f8e6ceaff73bf\",\"license\":\"UNLICENSED\"},\"interfaces/ICurve.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\ninterface ICurve {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\\n}\\n\\ninterface ICurveLegacy {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\\n}\\n\\n\",\"keccak256\":\"0x3d4940b3583e06dde20f12e92d2f6ac573b3f64bdaa1e8f480656a3763852518\",\"license\":\"UNLICENSED\"},\"interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/ITridentCLPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface ITridentCLPool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bool unwrapBento,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x572376b80c86a94692b0e27e6e63790b763295e32ba1f956c1d331fc1296de8d\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IUniswapV2Pair.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Pair {\\n event Approval(address indexed owner, address indexed spender, uint value);\\n event Transfer(address indexed from, address indexed to, uint value);\\n\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function allowance(address owner, address spender) external view returns (uint);\\n\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address to, uint value) external returns (bool);\\n function transferFrom(address from, address to, uint value) external returns (bool);\\n\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n function nonces(address owner) external view returns (uint);\\n\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n event Mint(address indexed sender, uint amount0, uint amount1);\\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\\n event Swap(\\n address indexed sender,\\n uint amount0In,\\n uint amount1In,\\n uint amount0Out,\\n uint amount1Out,\\n address indexed to\\n );\\n event Sync(uint112 reserve0, uint112 reserve1);\\n\\n function MINIMUM_LIQUIDITY() external pure returns (uint);\\n function factory() external view returns (address);\\n function token0() external view returns (address);\\n function token1() external view returns (address);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\\n function price0CumulativeLast() external view returns (uint);\\n function price1CumulativeLast() external view returns (uint);\\n function kLast() external view returns (uint);\\n\\n function mint(address to) external returns (uint liquidity);\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function skim(address to) external;\\n function sync() external;\\n\\n function initialize(address, address) external;\\n}\",\"keccak256\":\"0x08f9a63b34855eec941be8d36a04424f1a1725a2c030373fcef3afeb480ca385\",\"license\":\"GPL-3.0\"},\"interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IUniswapV3Pool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x2a4d7c6120e613f0e95d4dc8c650efb9b59e3c25c64e3e5c0a379281500f0a79\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IWETH.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0xae8529ae159f784b90fdcd0629bd03bf7b68accc81edccac53357ad08406a378\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}", + "bytecode": "0x60a06040526002805461ffff60a01b191661010160a01b1790553480156200002657600080fd5b50604051620040a3380380620040a383398101604081905262000049916200016e565b6200005433620000eb565b6001600160a01b038216608052600280546001600160a01b031916600117905560005b8151811015620000e25760018060008484815181106200009b576200009b62000257565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000d9816200026d565b91505062000077565b50505062000297565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200015357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200018257600080fd5b6200018d836200013b565b602084810151919350906001600160401b0380821115620001ad57600080fd5b818601915086601f830112620001c257600080fd5b815181811115620001d757620001d762000158565b8060051b604051601f19603f83011681018181108582111715620001ff57620001ff62000158565b6040529182528482019250838101850191898311156200021e57600080fd5b938501935b82851015620002475762000237856200013b565b8452938501939285019262000223565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200029057634e487b7160e01b600052601160045260246000fd5b5060010190565b608051613da3620003006000396000818161018d01528181611798015281816127380152818161279d01528181612807015281816128cc0152818161297901528181612a5d01528181612b6401528181612c1001528181612cdf0152612df10152613da36000f3fe6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "deployedBytecode": "0x6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "devdoc": { + "author": "Ilya Lyalin", + "kind": "dev", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IAlgebraPoolActions#swap call" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the PancakeV3Pool#swap call" + } + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "route": "Route to process", + "to": "Where to transfer output tokens", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IUniswapV3PoolActions#swap call" + } + } + }, + "title": "A route processor for the Sushi Aggregator", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IAlgebraPool#swap." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via PancakeV3Pool#swap." + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "notice": "Processes the route generated off-chain. Has a lock" + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value of input tokens to and then processes the route" + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "processes the route and sends amount of output token to " + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value to and then processes the route" + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 1060, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "priviledgedUsers", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 1062, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "lastCalledPool", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 1065, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "unlocked", + "offset": 20, + "slot": "2", + "type": "t_uint8" + }, + { + "astId": 1068, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "paused", + "offset": 21, + "slot": "2", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/skale-europa/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json b/protocols/route-processor/deployments/skale-europa/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json new file mode 100644 index 0000000000..01826e7b93 --- /dev/null +++ b/protocols/route-processor/deployments/skale-europa/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json @@ -0,0 +1,80 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" + }, + "contracts/InputStream.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" + }, + "contracts/RouteProcessor5.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" + }, + "contracts/Utils.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "interfaces/IBentoBoxMinimal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" + }, + "interfaces/ICurve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" + }, + "interfaces/IPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" + }, + "interfaces/ITridentCLPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/telos/RouteProcessor5.json b/protocols/route-processor/deployments/telos/RouteProcessor5.json new file mode 100644 index 0000000000..096f692cd3 --- /dev/null +++ b/protocols/route-processor/deployments/telos/RouteProcessor5.json @@ -0,0 +1,704 @@ +{ + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_bentoBox", + "type": "address" + }, + { + "internalType": "address[]", + "name": "priviledgedUserList", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "MinimalOutputBalanceViolation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Route", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "algebraSwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bentoBox", + "outputs": [ + { + "internalType": "contract IBentoBoxMinimal", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "pancakeV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "priviledgedUsers", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueInput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "priviledge", + "type": "bool" + } + ], + "name": "setPriviledge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "transferValueAndprocessRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0xe92221bb1c15707b3c22b237e0fe2287c20763b987ddcda27536b0e31988b9bf", + "receipt": { + "to": null, + "from": "0x282607716D9B4fDD0B094d5864fac56313f5e665", + "contractAddress": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "transactionIndex": 0, + "gasUsed": "3488833", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000080000000000000000000000000000000000000000001000000000000000002000000000004000000000000040000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x576c7648795205912b8bc0073f2fb1a6a9c6fbcb800f8186dac0e21ec5f1e87e", + "transactionHash": "0xe92221bb1c15707b3c22b237e0fe2287c20763b987ddcda27536b0e31988b9bf", + "logs": [ + { + "transactionIndex": 0, + "blockNumber": 354555202, + "transactionHash": "0xe92221bb1c15707b3c22b237e0fe2287c20763b987ddcda27536b0e31988b9bf", + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000282607716d9b4fdd0b094d5864fac56313f5e665" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0x576c7648795205912b8bc0073f2fb1a6a9c6fbcb800f8186dac0e21ec5f1e87e" + } + ], + "blockNumber": 354555202, + "cumulativeGasUsed": "3488833", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000000", + [] + ], + "numDeployments": 1, + "solcInputHash": "e556d43a3caf4f1fb4f12d632d103b28", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bentoBox\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"priviledgedUserList\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"MinimalOutputBalanceViolation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"Route\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"algebraSwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"pancakeV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"priviledgedUsers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"priviledge\",\"type\":\"bool\"}],\"name\":\"setPriviledge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"transferValueAndprocessRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"Ilya Lyalin\",\"kind\":\"dev\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IAlgebraPoolActions#swap call\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the PancakeV3Pool#swap call\"}},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"route\":\"Route to process\",\"to\":\"Where to transfer output tokens\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IUniswapV3PoolActions#swap call\"}}},\"title\":\"A route processor for the Sushi Aggregator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\"},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Processes the route generated off-chain. Has a lock\"},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value of input tokens to and then processes the route\"},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"processes the route and sends amount of output token to \"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value to and then processes the route\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RouteProcessor5.sol\":\"RouteProcessor5\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\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 Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.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 function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\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\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\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 * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\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\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/InputStream.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\n/** @notice Simple read stream */\\nlibrary InputStream {\\n\\n /** @notice Creates stream from data\\n * @param data data\\n */\\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\\n assembly {\\n stream := mload(0x40)\\n mstore(0x40, add(stream, 64))\\n mstore(stream, data)\\n let length := mload(data)\\n mstore(add(stream, 32), add(data, length))\\n }\\n }\\n\\n /** @notice Checks if stream is not empty\\n * @param stream stream\\n */\\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\\n uint256 pos;\\n uint256 finish;\\n assembly {\\n pos := mload(stream)\\n finish := mload(add(stream, 32))\\n }\\n return pos < finish;\\n }\\n\\n /** @notice Reads uint8 from the stream\\n * @param stream stream\\n */\\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 1)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint16 from the stream\\n * @param stream stream\\n */\\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 2)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint24 from the stream\\n * @param stream stream\\n */\\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 3)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint32 from the stream\\n * @param stream stream\\n */\\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 4)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint256 from the stream\\n * @param stream stream\\n */\\n function readUint(uint256 stream) internal pure returns (uint256 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes32 from the stream\\n * @param stream stream\\n */\\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads address from the stream\\n * @param stream stream\\n */\\n function readAddress(uint256 stream) internal pure returns (address res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 20)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes from the stream\\n * @param stream stream\\n */\\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\\n assembly {\\n let pos := mload(stream)\\n res := add(pos, 32)\\n let length := mload(res)\\n mstore(stream, add(res, length))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x24e24bd0e49cbddacbf3b26bcd4bdffac63d11f3259bc05bc93c0835e8ff5300\",\"license\":\"UNLICENSED\"},\"contracts/RouteProcessor5.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '../interfaces/IUniswapV2Pair.sol';\\nimport '../interfaces/IUniswapV3Pool.sol';\\nimport '../interfaces/ITridentCLPool.sol';\\nimport '../interfaces/IBentoBoxMinimal.sol';\\nimport '../interfaces/IPool.sol';\\nimport '../interfaces/IWETH.sol';\\nimport '../interfaces/ICurve.sol';\\nimport './InputStream.sol';\\nimport './Utils.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\\n\\nuint8 constant LOCKED = 2;\\nuint8 constant NOT_LOCKED = 1;\\nuint8 constant PAUSED = 2;\\nuint8 constant NOT_PAUSED = 1;\\n\\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\nuint160 constant MIN_SQRT_RATIO = 4295128739;\\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n/// @title A route processor for the Sushi Aggregator\\n/// @author Ilya Lyalin\\ncontract RouteProcessor5 is Ownable {\\n using SafeERC20 for IERC20;\\n using Utils for IERC20;\\n using Utils for address;\\n using SafeERC20 for IERC20Permit;\\n using InputStream for uint256;\\n\\n event Route(\\n address indexed from, \\n address to, \\n address indexed tokenIn, \\n address indexed tokenOut, \\n uint256 amountIn, \\n uint256 amountOutMin,\\n uint256 amountOut\\n );\\n\\n error MinimalOutputBalanceViolation(uint256 amountOut);\\n\\n IBentoBoxMinimal public immutable bentoBox;\\n mapping (address => bool) public priviledgedUsers;\\n address private lastCalledPool;\\n\\n uint8 private unlocked = NOT_LOCKED;\\n uint8 private paused = NOT_PAUSED;\\n modifier lock() {\\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\\n unlocked = LOCKED;\\n _;\\n unlocked = NOT_LOCKED;\\n }\\n\\n modifier onlyOwnerOrPriviledgedUser() {\\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \\\"RP: caller is not the owner or a privileged user\\\");\\n _;\\n }\\n\\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\\n bentoBox = IBentoBoxMinimal(_bentoBox);\\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n\\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\\n priviledgedUsers[priviledgedUserList[i]] = true;\\n }\\n }\\n\\n function setPriviledge(address user, bool priviledge) external onlyOwner {\\n priviledgedUsers[user] = priviledge;\\n }\\n\\n function pause() external onlyOwnerOrPriviledgedUser {\\n paused = PAUSED;\\n }\\n\\n function resume() external onlyOwnerOrPriviledgedUser {\\n paused = NOT_PAUSED;\\n }\\n\\n /// @notice For native unwrapping\\n receive() external payable {}\\n\\n /// @notice Processes the route generated off-chain. Has a lock\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @param to Where to transfer output tokens\\n /// @param route Route to process\\n /// @return amountOut Actual amount of the output token\\n function processRoute(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function transferValueAndprocessRoute(\\n address transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n transferValueTo.transferNative(amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value of input tokens to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueInput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n \\n /// @notice processes the route and sends amount of output token to \\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueOutput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\\n }\\n\\n /// @notice Processes the route generated off-chain\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteInternal(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) private returns (uint256 amountOut) {\\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\\n\\n uint256 realAmountIn = amountIn;\\n {\\n uint256 step = 0;\\n uint256 stream = InputStream.createStream(route);\\n while (stream.isNotEmpty()) {\\n uint8 commandCode = stream.readUint8();\\n if (commandCode == 1) {\\n uint256 usedAmount = processMyERC20(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 2) processUserERC20(stream, amountIn);\\n else if (commandCode == 3) {\\n uint256 usedAmount = processNative(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 4) processOnePool(stream);\\n else if (commandCode == 5) processInsideBento(stream);\\n else if (commandCode == 6) applyPermit(tokenIn, stream);\\n else revert('RouteProcessor: Unknown command code');\\n ++step;\\n }\\n }\\n\\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\\n if (tokenIn != Utils.NATIVE_ADDRESS)\\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\\n \\n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\\n\\n amountOut = balanceOutFinal - balanceOutInitial;\\n\\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\\n }\\n\\n /// @notice Applies ERC-2612 permit\\n /// @param tokenIn permitted token\\n /// @param stream Streamed program\\n function applyPermit(address tokenIn, uint256 stream) private {\\n uint256 value = stream.readUint();\\n uint256 deadline = stream.readUint();\\n uint8 v = stream.readUint8();\\n bytes32 r = stream.readBytes32();\\n bytes32 s = stream.readBytes32();\\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\\n }\\n }\\n\\n /// @notice Processes native coin: call swap for all pools that swap from native coin\\n /// @param stream Streamed program\\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\\n amountTotal = address(this).balance;\\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token from this contract balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\\n address token = stream.readAddress();\\n amountTotal = IERC20(token).balanceOf(address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n \\n /// @notice Processes ERC20 token from msg.sender balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n /// @param amountTotal Amount of tokens to take from msg.sender\\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\\n address token = stream.readAddress();\\n distributeAndSwap(stream, msg.sender, token, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token for cases when the token has only one output pool\\n /// @notice In this case liquidity is already at pool balance. This is an optimization\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processOnePool(uint256 stream) private {\\n address token = stream.readAddress();\\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\\n }\\n\\n /// @notice Processes Bento tokens \\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processInsideBento(uint256 stream) private {\\n address token = stream.readAddress();\\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n\\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountTotal Total amount of tokenIn for swaps \\n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\\n uint8 num = stream.readUint8();\\n unchecked {\\n for (uint256 i = 0; i < num; ++i) {\\n uint16 share = stream.readUint16();\\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\\n amountTotal -= amount;\\n swap(stream, from, tokenIn, amount);\\n }\\n }\\n }\\n\\n /// @notice Makes swap\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 poolType = stream.readUint8();\\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\\n else revert('RouteProcessor: Unknown pool type');\\n }\\n\\n /// @notice Wraps/unwraps native token\\n /// @param stream [direction & fake, recipient, wrapToken?]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 directionAndFake = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (directionAndFake & 1 == 1) { // wrap native\\n address wrapToken = stream.readAddress();\\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\\n } else { // unwrap native\\n if (directionAndFake & 2 == 0) {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IWETH(tokenIn).withdraw(amountIn);\\n }\\n to.transferNative(amountIn);\\n }\\n }\\n\\n /// @notice Bridge/unbridge tokens to/from Bento\\n /// @param stream [direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (direction > 0) { // outside to Bento\\n // deposit to arbitrary recipient is possible only from address(bentoBox)\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\\n else {\\n // tokens already are at address(bentoBox)\\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\\n bentoBox.strategyData(tokenIn).balance -\\n bentoBox.totals(tokenIn).elastic;\\n }\\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\\n } else { // Bento to outside\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\\n }\\n }\\n\\n /// @notice UniswapV2 pool swap\\n /// @param stream [pool, direction, recipient, fee]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\\n\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\\n\\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\\n\\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\\n }\\n\\n /// @notice Trident pool swap\\n /// @param stream [pool, swapData]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bytes memory swapData = stream.readBytes();\\n\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, pool, amountIn);\\n }\\n \\n IPool(pool).swap(swapData);\\n }\\n\\n /// @notice UniswapV3 pool swap\\n /// @param stream [pool, direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bool zeroForOne = stream.readUint8() > 0;\\n address recipient = stream.readAddress();\\n\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\\n\\n lastCalledPool = pool;\\n IUniswapV3Pool(pool).swap(\\n recipient,\\n zeroForOne,\\n int256(amountIn),\\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\\n abi.encode(tokenIn)\\n );\\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) public {\\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\\n \\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n (address tokenIn) = abi.decode(data, (address));\\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\\n function algebraSwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\\n function pancakeV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 poolType = stream.readUint8();\\n int128 fromIndex = int8(stream.readUint8());\\n int128 toIndex = int8(stream.readUint8());\\n address to = stream.readAddress();\\n address tokenOut = stream.readAddress();\\n\\n uint256 amountOut;\\n if (tokenIn == Utils.NATIVE_ADDRESS) {\\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\\n } else {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IERC20(tokenIn).approveSafe(pool, amountIn);\\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n else {\\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\\n amountOut = balanceAfter - balanceBefore;\\n }\\n }\\n\\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\\n }\\n}\\n\",\"keccak256\":\"0xcd53a7f473f1847d44c42777a194203cbff02b8c761cb2935402401f57c918a2\",\"license\":\"UNLICENSED\"},\"contracts/Utils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\n\\nlibrary Utils {\\n using SafeERC20 for IERC20;\\n\\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n /**\\n * @dev returns user's balance of token (or native)\\n */\\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\\n if (token == NATIVE_ADDRESS) return address(user).balance;\\n else return IERC20(token).balanceOf(user);\\n }\\n\\n /**\\n * @dev transfers native with correct revert bubble up\\n */\\n function transferNative(address to, uint256 amount) internal {\\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\\n if (!success) {\\n assembly {\\n revert(add(32, returnBytes), mload(returnBytes))\\n }\\n }\\n }\\n\\n /**\\n * @dev transfers ERC20 or native\\n */\\n function transferAny(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\\n else IERC20(token).safeTransfer(to, amount);\\n }\\n\\n /**\\n * @dev transfers from ERC20 or transfers native\\n */\\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n (bool success, bytes memory data) = address(token).call(\\n abi.encodeWithSelector(token.approve.selector, spender, amount)\\n );\\n return success && (data.length == 0 || abi.decode(data, (bool)));\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \\n * current allowance are not zero simultaniously (USDT for example). \\n * In second case it tries to set allowance to 0, and then back to amount.\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n return approveStable(token, spender, amount) \\n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\\n }\\n}\\n\",\"keccak256\":\"0x8c8439edc00b403abd3f34be75a06b1fe71152644ae9f19488af596bbc534ffe\",\"license\":\"UNLICENSED\"},\"interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\nstruct StrategyData {\\n uint64 strategyStartDate;\\n uint64 targetPercentage;\\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n function strategyData(address token) external view returns (StrategyData memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0x0c12eba7a5b9d22d37ab8883fe22d6a312a90682809dbd11c43f8e6ceaff73bf\",\"license\":\"UNLICENSED\"},\"interfaces/ICurve.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\ninterface ICurve {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\\n}\\n\\ninterface ICurveLegacy {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\\n}\\n\\n\",\"keccak256\":\"0x3d4940b3583e06dde20f12e92d2f6ac573b3f64bdaa1e8f480656a3763852518\",\"license\":\"UNLICENSED\"},\"interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/ITridentCLPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface ITridentCLPool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bool unwrapBento,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x572376b80c86a94692b0e27e6e63790b763295e32ba1f956c1d331fc1296de8d\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IUniswapV2Pair.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Pair {\\n event Approval(address indexed owner, address indexed spender, uint value);\\n event Transfer(address indexed from, address indexed to, uint value);\\n\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function allowance(address owner, address spender) external view returns (uint);\\n\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address to, uint value) external returns (bool);\\n function transferFrom(address from, address to, uint value) external returns (bool);\\n\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n function nonces(address owner) external view returns (uint);\\n\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n event Mint(address indexed sender, uint amount0, uint amount1);\\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\\n event Swap(\\n address indexed sender,\\n uint amount0In,\\n uint amount1In,\\n uint amount0Out,\\n uint amount1Out,\\n address indexed to\\n );\\n event Sync(uint112 reserve0, uint112 reserve1);\\n\\n function MINIMUM_LIQUIDITY() external pure returns (uint);\\n function factory() external view returns (address);\\n function token0() external view returns (address);\\n function token1() external view returns (address);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\\n function price0CumulativeLast() external view returns (uint);\\n function price1CumulativeLast() external view returns (uint);\\n function kLast() external view returns (uint);\\n\\n function mint(address to) external returns (uint liquidity);\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function skim(address to) external;\\n function sync() external;\\n\\n function initialize(address, address) external;\\n}\",\"keccak256\":\"0x08f9a63b34855eec941be8d36a04424f1a1725a2c030373fcef3afeb480ca385\",\"license\":\"GPL-3.0\"},\"interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IUniswapV3Pool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x2a4d7c6120e613f0e95d4dc8c650efb9b59e3c25c64e3e5c0a379281500f0a79\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IWETH.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0xae8529ae159f784b90fdcd0629bd03bf7b68accc81edccac53357ad08406a378\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}", + "bytecode": "0x60a06040526002805461ffff60a01b191661010160a01b1790553480156200002657600080fd5b50604051620040a3380380620040a383398101604081905262000049916200016e565b6200005433620000eb565b6001600160a01b038216608052600280546001600160a01b031916600117905560005b8151811015620000e25760018060008484815181106200009b576200009b62000257565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000d9816200026d565b91505062000077565b50505062000297565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200015357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200018257600080fd5b6200018d836200013b565b602084810151919350906001600160401b0380821115620001ad57600080fd5b818601915086601f830112620001c257600080fd5b815181811115620001d757620001d762000158565b8060051b604051601f19603f83011681018181108582111715620001ff57620001ff62000158565b6040529182528482019250838101850191898311156200021e57600080fd5b938501935b82851015620002475762000237856200013b565b8452938501939285019262000223565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200029057634e487b7160e01b600052601160045260246000fd5b5060010190565b608051613da3620003006000396000818161018d01528181611798015281816127380152818161279d01528181612807015281816128cc0152818161297901528181612a5d01528181612b6401528181612c1001528181612cdf0152612df10152613da36000f3fe6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "deployedBytecode": "0x6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "devdoc": { + "author": "Ilya Lyalin", + "kind": "dev", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IAlgebraPoolActions#swap call" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the PancakeV3Pool#swap call" + } + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "route": "Route to process", + "to": "Where to transfer output tokens", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IUniswapV3PoolActions#swap call" + } + } + }, + "title": "A route processor for the Sushi Aggregator", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IAlgebraPool#swap." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via PancakeV3Pool#swap." + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "notice": "Processes the route generated off-chain. Has a lock" + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value of input tokens to and then processes the route" + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "processes the route and sends amount of output token to " + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value to and then processes the route" + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 1060, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "priviledgedUsers", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 1062, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "lastCalledPool", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 1065, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "unlocked", + "offset": 20, + "slot": "2", + "type": "t_uint8" + }, + { + "astId": 1068, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "paused", + "offset": 21, + "slot": "2", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/telos/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json b/protocols/route-processor/deployments/telos/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json new file mode 100644 index 0000000000..01826e7b93 --- /dev/null +++ b/protocols/route-processor/deployments/telos/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json @@ -0,0 +1,80 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" + }, + "contracts/InputStream.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" + }, + "contracts/RouteProcessor5.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" + }, + "contracts/Utils.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "interfaces/IBentoBoxMinimal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" + }, + "interfaces/ICurve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" + }, + "interfaces/IPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" + }, + "interfaces/ITridentCLPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/thundercore/RouteProcessor5.json b/protocols/route-processor/deployments/thundercore/RouteProcessor5.json new file mode 100644 index 0000000000..76d96f1c86 --- /dev/null +++ b/protocols/route-processor/deployments/thundercore/RouteProcessor5.json @@ -0,0 +1,704 @@ +{ + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_bentoBox", + "type": "address" + }, + { + "internalType": "address[]", + "name": "priviledgedUserList", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "MinimalOutputBalanceViolation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Route", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "algebraSwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bentoBox", + "outputs": [ + { + "internalType": "contract IBentoBoxMinimal", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "pancakeV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "priviledgedUsers", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueInput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "priviledge", + "type": "bool" + } + ], + "name": "setPriviledge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "transferValueAndprocessRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x916b3b36a0e1d5951a6f4caede798228667ac10815f1dea386f3796026543908", + "receipt": { + "to": null, + "from": "0x282607716D9B4fDD0B094d5864fac56313f5e665", + "contractAddress": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "transactionIndex": 0, + "gasUsed": "3536833", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000020000000000000000000000000000000000000001000000000000000000000000000000000000000000040000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000000000000000000000000000", + "blockHash": "0xd99ffab59cf32081c598032d0d6f3e4bd3f10f6c7d1ca5c6e196de181d80845d", + "transactionHash": "0x916b3b36a0e1d5951a6f4caede798228667ac10815f1dea386f3796026543908", + "logs": [ + { + "transactionIndex": 0, + "blockNumber": 170134094, + "transactionHash": "0x916b3b36a0e1d5951a6f4caede798228667ac10815f1dea386f3796026543908", + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000282607716d9b4fdd0b094d5864fac56313f5e665" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0xd99ffab59cf32081c598032d0d6f3e4bd3f10f6c7d1ca5c6e196de181d80845d" + } + ], + "blockNumber": 170134094, + "cumulativeGasUsed": "3536833", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000000", + [] + ], + "numDeployments": 1, + "solcInputHash": "e556d43a3caf4f1fb4f12d632d103b28", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bentoBox\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"priviledgedUserList\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"MinimalOutputBalanceViolation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"Route\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"algebraSwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"pancakeV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"priviledgedUsers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"priviledge\",\"type\":\"bool\"}],\"name\":\"setPriviledge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"transferValueAndprocessRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"Ilya Lyalin\",\"kind\":\"dev\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IAlgebraPoolActions#swap call\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the PancakeV3Pool#swap call\"}},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"route\":\"Route to process\",\"to\":\"Where to transfer output tokens\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IUniswapV3PoolActions#swap call\"}}},\"title\":\"A route processor for the Sushi Aggregator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\"},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Processes the route generated off-chain. Has a lock\"},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value of input tokens to and then processes the route\"},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"processes the route and sends amount of output token to \"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value to and then processes the route\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RouteProcessor5.sol\":\"RouteProcessor5\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\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 Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.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 function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\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\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\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 * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\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\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/InputStream.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\n/** @notice Simple read stream */\\nlibrary InputStream {\\n\\n /** @notice Creates stream from data\\n * @param data data\\n */\\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\\n assembly {\\n stream := mload(0x40)\\n mstore(0x40, add(stream, 64))\\n mstore(stream, data)\\n let length := mload(data)\\n mstore(add(stream, 32), add(data, length))\\n }\\n }\\n\\n /** @notice Checks if stream is not empty\\n * @param stream stream\\n */\\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\\n uint256 pos;\\n uint256 finish;\\n assembly {\\n pos := mload(stream)\\n finish := mload(add(stream, 32))\\n }\\n return pos < finish;\\n }\\n\\n /** @notice Reads uint8 from the stream\\n * @param stream stream\\n */\\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 1)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint16 from the stream\\n * @param stream stream\\n */\\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 2)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint24 from the stream\\n * @param stream stream\\n */\\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 3)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint32 from the stream\\n * @param stream stream\\n */\\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 4)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint256 from the stream\\n * @param stream stream\\n */\\n function readUint(uint256 stream) internal pure returns (uint256 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes32 from the stream\\n * @param stream stream\\n */\\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads address from the stream\\n * @param stream stream\\n */\\n function readAddress(uint256 stream) internal pure returns (address res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 20)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes from the stream\\n * @param stream stream\\n */\\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\\n assembly {\\n let pos := mload(stream)\\n res := add(pos, 32)\\n let length := mload(res)\\n mstore(stream, add(res, length))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x24e24bd0e49cbddacbf3b26bcd4bdffac63d11f3259bc05bc93c0835e8ff5300\",\"license\":\"UNLICENSED\"},\"contracts/RouteProcessor5.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '../interfaces/IUniswapV2Pair.sol';\\nimport '../interfaces/IUniswapV3Pool.sol';\\nimport '../interfaces/ITridentCLPool.sol';\\nimport '../interfaces/IBentoBoxMinimal.sol';\\nimport '../interfaces/IPool.sol';\\nimport '../interfaces/IWETH.sol';\\nimport '../interfaces/ICurve.sol';\\nimport './InputStream.sol';\\nimport './Utils.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\\n\\nuint8 constant LOCKED = 2;\\nuint8 constant NOT_LOCKED = 1;\\nuint8 constant PAUSED = 2;\\nuint8 constant NOT_PAUSED = 1;\\n\\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\nuint160 constant MIN_SQRT_RATIO = 4295128739;\\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n/// @title A route processor for the Sushi Aggregator\\n/// @author Ilya Lyalin\\ncontract RouteProcessor5 is Ownable {\\n using SafeERC20 for IERC20;\\n using Utils for IERC20;\\n using Utils for address;\\n using SafeERC20 for IERC20Permit;\\n using InputStream for uint256;\\n\\n event Route(\\n address indexed from, \\n address to, \\n address indexed tokenIn, \\n address indexed tokenOut, \\n uint256 amountIn, \\n uint256 amountOutMin,\\n uint256 amountOut\\n );\\n\\n error MinimalOutputBalanceViolation(uint256 amountOut);\\n\\n IBentoBoxMinimal public immutable bentoBox;\\n mapping (address => bool) public priviledgedUsers;\\n address private lastCalledPool;\\n\\n uint8 private unlocked = NOT_LOCKED;\\n uint8 private paused = NOT_PAUSED;\\n modifier lock() {\\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\\n unlocked = LOCKED;\\n _;\\n unlocked = NOT_LOCKED;\\n }\\n\\n modifier onlyOwnerOrPriviledgedUser() {\\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \\\"RP: caller is not the owner or a privileged user\\\");\\n _;\\n }\\n\\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\\n bentoBox = IBentoBoxMinimal(_bentoBox);\\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n\\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\\n priviledgedUsers[priviledgedUserList[i]] = true;\\n }\\n }\\n\\n function setPriviledge(address user, bool priviledge) external onlyOwner {\\n priviledgedUsers[user] = priviledge;\\n }\\n\\n function pause() external onlyOwnerOrPriviledgedUser {\\n paused = PAUSED;\\n }\\n\\n function resume() external onlyOwnerOrPriviledgedUser {\\n paused = NOT_PAUSED;\\n }\\n\\n /// @notice For native unwrapping\\n receive() external payable {}\\n\\n /// @notice Processes the route generated off-chain. Has a lock\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @param to Where to transfer output tokens\\n /// @param route Route to process\\n /// @return amountOut Actual amount of the output token\\n function processRoute(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function transferValueAndprocessRoute(\\n address transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n transferValueTo.transferNative(amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value of input tokens to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueInput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n \\n /// @notice processes the route and sends amount of output token to \\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueOutput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\\n }\\n\\n /// @notice Processes the route generated off-chain\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteInternal(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) private returns (uint256 amountOut) {\\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\\n\\n uint256 realAmountIn = amountIn;\\n {\\n uint256 step = 0;\\n uint256 stream = InputStream.createStream(route);\\n while (stream.isNotEmpty()) {\\n uint8 commandCode = stream.readUint8();\\n if (commandCode == 1) {\\n uint256 usedAmount = processMyERC20(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 2) processUserERC20(stream, amountIn);\\n else if (commandCode == 3) {\\n uint256 usedAmount = processNative(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 4) processOnePool(stream);\\n else if (commandCode == 5) processInsideBento(stream);\\n else if (commandCode == 6) applyPermit(tokenIn, stream);\\n else revert('RouteProcessor: Unknown command code');\\n ++step;\\n }\\n }\\n\\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\\n if (tokenIn != Utils.NATIVE_ADDRESS)\\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\\n \\n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\\n\\n amountOut = balanceOutFinal - balanceOutInitial;\\n\\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\\n }\\n\\n /// @notice Applies ERC-2612 permit\\n /// @param tokenIn permitted token\\n /// @param stream Streamed program\\n function applyPermit(address tokenIn, uint256 stream) private {\\n uint256 value = stream.readUint();\\n uint256 deadline = stream.readUint();\\n uint8 v = stream.readUint8();\\n bytes32 r = stream.readBytes32();\\n bytes32 s = stream.readBytes32();\\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\\n }\\n }\\n\\n /// @notice Processes native coin: call swap for all pools that swap from native coin\\n /// @param stream Streamed program\\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\\n amountTotal = address(this).balance;\\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token from this contract balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\\n address token = stream.readAddress();\\n amountTotal = IERC20(token).balanceOf(address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n \\n /// @notice Processes ERC20 token from msg.sender balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n /// @param amountTotal Amount of tokens to take from msg.sender\\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\\n address token = stream.readAddress();\\n distributeAndSwap(stream, msg.sender, token, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token for cases when the token has only one output pool\\n /// @notice In this case liquidity is already at pool balance. This is an optimization\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processOnePool(uint256 stream) private {\\n address token = stream.readAddress();\\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\\n }\\n\\n /// @notice Processes Bento tokens \\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processInsideBento(uint256 stream) private {\\n address token = stream.readAddress();\\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n\\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountTotal Total amount of tokenIn for swaps \\n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\\n uint8 num = stream.readUint8();\\n unchecked {\\n for (uint256 i = 0; i < num; ++i) {\\n uint16 share = stream.readUint16();\\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\\n amountTotal -= amount;\\n swap(stream, from, tokenIn, amount);\\n }\\n }\\n }\\n\\n /// @notice Makes swap\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 poolType = stream.readUint8();\\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\\n else revert('RouteProcessor: Unknown pool type');\\n }\\n\\n /// @notice Wraps/unwraps native token\\n /// @param stream [direction & fake, recipient, wrapToken?]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 directionAndFake = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (directionAndFake & 1 == 1) { // wrap native\\n address wrapToken = stream.readAddress();\\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\\n } else { // unwrap native\\n if (directionAndFake & 2 == 0) {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IWETH(tokenIn).withdraw(amountIn);\\n }\\n to.transferNative(amountIn);\\n }\\n }\\n\\n /// @notice Bridge/unbridge tokens to/from Bento\\n /// @param stream [direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (direction > 0) { // outside to Bento\\n // deposit to arbitrary recipient is possible only from address(bentoBox)\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\\n else {\\n // tokens already are at address(bentoBox)\\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\\n bentoBox.strategyData(tokenIn).balance -\\n bentoBox.totals(tokenIn).elastic;\\n }\\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\\n } else { // Bento to outside\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\\n }\\n }\\n\\n /// @notice UniswapV2 pool swap\\n /// @param stream [pool, direction, recipient, fee]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\\n\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\\n\\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\\n\\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\\n }\\n\\n /// @notice Trident pool swap\\n /// @param stream [pool, swapData]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bytes memory swapData = stream.readBytes();\\n\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, pool, amountIn);\\n }\\n \\n IPool(pool).swap(swapData);\\n }\\n\\n /// @notice UniswapV3 pool swap\\n /// @param stream [pool, direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bool zeroForOne = stream.readUint8() > 0;\\n address recipient = stream.readAddress();\\n\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\\n\\n lastCalledPool = pool;\\n IUniswapV3Pool(pool).swap(\\n recipient,\\n zeroForOne,\\n int256(amountIn),\\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\\n abi.encode(tokenIn)\\n );\\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) public {\\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\\n \\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n (address tokenIn) = abi.decode(data, (address));\\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\\n function algebraSwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\\n function pancakeV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 poolType = stream.readUint8();\\n int128 fromIndex = int8(stream.readUint8());\\n int128 toIndex = int8(stream.readUint8());\\n address to = stream.readAddress();\\n address tokenOut = stream.readAddress();\\n\\n uint256 amountOut;\\n if (tokenIn == Utils.NATIVE_ADDRESS) {\\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\\n } else {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IERC20(tokenIn).approveSafe(pool, amountIn);\\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n else {\\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\\n amountOut = balanceAfter - balanceBefore;\\n }\\n }\\n\\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\\n }\\n}\\n\",\"keccak256\":\"0xcd53a7f473f1847d44c42777a194203cbff02b8c761cb2935402401f57c918a2\",\"license\":\"UNLICENSED\"},\"contracts/Utils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\n\\nlibrary Utils {\\n using SafeERC20 for IERC20;\\n\\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n /**\\n * @dev returns user's balance of token (or native)\\n */\\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\\n if (token == NATIVE_ADDRESS) return address(user).balance;\\n else return IERC20(token).balanceOf(user);\\n }\\n\\n /**\\n * @dev transfers native with correct revert bubble up\\n */\\n function transferNative(address to, uint256 amount) internal {\\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\\n if (!success) {\\n assembly {\\n revert(add(32, returnBytes), mload(returnBytes))\\n }\\n }\\n }\\n\\n /**\\n * @dev transfers ERC20 or native\\n */\\n function transferAny(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\\n else IERC20(token).safeTransfer(to, amount);\\n }\\n\\n /**\\n * @dev transfers from ERC20 or transfers native\\n */\\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n (bool success, bytes memory data) = address(token).call(\\n abi.encodeWithSelector(token.approve.selector, spender, amount)\\n );\\n return success && (data.length == 0 || abi.decode(data, (bool)));\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \\n * current allowance are not zero simultaniously (USDT for example). \\n * In second case it tries to set allowance to 0, and then back to amount.\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n return approveStable(token, spender, amount) \\n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\\n }\\n}\\n\",\"keccak256\":\"0x8c8439edc00b403abd3f34be75a06b1fe71152644ae9f19488af596bbc534ffe\",\"license\":\"UNLICENSED\"},\"interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\nstruct StrategyData {\\n uint64 strategyStartDate;\\n uint64 targetPercentage;\\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n function strategyData(address token) external view returns (StrategyData memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0x0c12eba7a5b9d22d37ab8883fe22d6a312a90682809dbd11c43f8e6ceaff73bf\",\"license\":\"UNLICENSED\"},\"interfaces/ICurve.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\ninterface ICurve {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\\n}\\n\\ninterface ICurveLegacy {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\\n}\\n\\n\",\"keccak256\":\"0x3d4940b3583e06dde20f12e92d2f6ac573b3f64bdaa1e8f480656a3763852518\",\"license\":\"UNLICENSED\"},\"interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/ITridentCLPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface ITridentCLPool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bool unwrapBento,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x572376b80c86a94692b0e27e6e63790b763295e32ba1f956c1d331fc1296de8d\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IUniswapV2Pair.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Pair {\\n event Approval(address indexed owner, address indexed spender, uint value);\\n event Transfer(address indexed from, address indexed to, uint value);\\n\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function allowance(address owner, address spender) external view returns (uint);\\n\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address to, uint value) external returns (bool);\\n function transferFrom(address from, address to, uint value) external returns (bool);\\n\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n function nonces(address owner) external view returns (uint);\\n\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n event Mint(address indexed sender, uint amount0, uint amount1);\\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\\n event Swap(\\n address indexed sender,\\n uint amount0In,\\n uint amount1In,\\n uint amount0Out,\\n uint amount1Out,\\n address indexed to\\n );\\n event Sync(uint112 reserve0, uint112 reserve1);\\n\\n function MINIMUM_LIQUIDITY() external pure returns (uint);\\n function factory() external view returns (address);\\n function token0() external view returns (address);\\n function token1() external view returns (address);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\\n function price0CumulativeLast() external view returns (uint);\\n function price1CumulativeLast() external view returns (uint);\\n function kLast() external view returns (uint);\\n\\n function mint(address to) external returns (uint liquidity);\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function skim(address to) external;\\n function sync() external;\\n\\n function initialize(address, address) external;\\n}\",\"keccak256\":\"0x08f9a63b34855eec941be8d36a04424f1a1725a2c030373fcef3afeb480ca385\",\"license\":\"GPL-3.0\"},\"interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IUniswapV3Pool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x2a4d7c6120e613f0e95d4dc8c650efb9b59e3c25c64e3e5c0a379281500f0a79\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IWETH.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0xae8529ae159f784b90fdcd0629bd03bf7b68accc81edccac53357ad08406a378\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}", + "bytecode": "0x60a06040526002805461ffff60a01b191661010160a01b1790553480156200002657600080fd5b50604051620040a3380380620040a383398101604081905262000049916200016e565b6200005433620000eb565b6001600160a01b038216608052600280546001600160a01b031916600117905560005b8151811015620000e25760018060008484815181106200009b576200009b62000257565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000d9816200026d565b91505062000077565b50505062000297565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200015357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200018257600080fd5b6200018d836200013b565b602084810151919350906001600160401b0380821115620001ad57600080fd5b818601915086601f830112620001c257600080fd5b815181811115620001d757620001d762000158565b8060051b604051601f19603f83011681018181108582111715620001ff57620001ff62000158565b6040529182528482019250838101850191898311156200021e57600080fd5b938501935b82851015620002475762000237856200013b565b8452938501939285019262000223565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200029057634e487b7160e01b600052601160045260246000fd5b5060010190565b608051613da3620003006000396000818161018d01528181611798015281816127380152818161279d01528181612807015281816128cc0152818161297901528181612a5d01528181612b6401528181612c1001528181612cdf0152612df10152613da36000f3fe6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "deployedBytecode": "0x6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "devdoc": { + "author": "Ilya Lyalin", + "kind": "dev", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IAlgebraPoolActions#swap call" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the PancakeV3Pool#swap call" + } + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "route": "Route to process", + "to": "Where to transfer output tokens", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IUniswapV3PoolActions#swap call" + } + } + }, + "title": "A route processor for the Sushi Aggregator", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IAlgebraPool#swap." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via PancakeV3Pool#swap." + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "notice": "Processes the route generated off-chain. Has a lock" + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value of input tokens to and then processes the route" + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "processes the route and sends amount of output token to " + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value to and then processes the route" + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 1060, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "priviledgedUsers", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 1062, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "lastCalledPool", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 1065, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "unlocked", + "offset": 20, + "slot": "2", + "type": "t_uint8" + }, + { + "astId": 1068, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "paused", + "offset": 21, + "slot": "2", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/thundercore/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json b/protocols/route-processor/deployments/thundercore/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json new file mode 100644 index 0000000000..01826e7b93 --- /dev/null +++ b/protocols/route-processor/deployments/thundercore/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json @@ -0,0 +1,80 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" + }, + "contracts/InputStream.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" + }, + "contracts/RouteProcessor5.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" + }, + "contracts/Utils.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "interfaces/IBentoBoxMinimal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" + }, + "interfaces/ICurve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" + }, + "interfaces/IPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" + }, + "interfaces/ITridentCLPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/zetachain/RouteProcessor5.json b/protocols/route-processor/deployments/zetachain/RouteProcessor5.json new file mode 100644 index 0000000000..c2b5bf8007 --- /dev/null +++ b/protocols/route-processor/deployments/zetachain/RouteProcessor5.json @@ -0,0 +1,704 @@ +{ + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_bentoBox", + "type": "address" + }, + { + "internalType": "address[]", + "name": "priviledgedUserList", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "MinimalOutputBalanceViolation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Route", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "algebraSwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bentoBox", + "outputs": [ + { + "internalType": "contract IBentoBoxMinimal", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "pancakeV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "priviledgedUsers", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueInput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "priviledge", + "type": "bool" + } + ], + "name": "setPriviledge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "transferValueAndprocessRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x4217a9ca2cae12c56541d6d76b8aeb4c9bdcefe9f1d0d59f44f9906e46047f7e", + "receipt": { + "to": null, + "from": "0x282607716D9B4fDD0B094d5864fac56313f5e665", + "contractAddress": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "transactionIndex": 1, + "gasUsed": "3488833", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000020000000000000000000000000000000000000001000000000000000000000000000000000000000000040000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000000000000000000000000000", + "blockHash": "0xe45956f2f2374855d3c20c3ff75bcf8f07b5c8eb91cdf0e5699de17652d09c8f", + "transactionHash": "0x4217a9ca2cae12c56541d6d76b8aeb4c9bdcefe9f1d0d59f44f9906e46047f7e", + "logs": [ + { + "transactionIndex": 1, + "blockNumber": 4155481, + "transactionHash": "0x4217a9ca2cae12c56541d6d76b8aeb4c9bdcefe9f1d0d59f44f9906e46047f7e", + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000282607716d9b4fdd0b094d5864fac56313f5e665" + ], + "data": "0x", + "logIndex": 1, + "blockHash": "0xe45956f2f2374855d3c20c3ff75bcf8f07b5c8eb91cdf0e5699de17652d09c8f" + } + ], + "blockNumber": 4155481, + "cumulativeGasUsed": "3638833", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000000", + [] + ], + "numDeployments": 1, + "solcInputHash": "e556d43a3caf4f1fb4f12d632d103b28", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bentoBox\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"priviledgedUserList\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"MinimalOutputBalanceViolation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"Route\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"algebraSwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"pancakeV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"priviledgedUsers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"priviledge\",\"type\":\"bool\"}],\"name\":\"setPriviledge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"transferValueAndprocessRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"Ilya Lyalin\",\"kind\":\"dev\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IAlgebraPoolActions#swap call\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the PancakeV3Pool#swap call\"}},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"route\":\"Route to process\",\"to\":\"Where to transfer output tokens\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IUniswapV3PoolActions#swap call\"}}},\"title\":\"A route processor for the Sushi Aggregator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\"},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Processes the route generated off-chain. Has a lock\"},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value of input tokens to and then processes the route\"},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"processes the route and sends amount of output token to \"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value to and then processes the route\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RouteProcessor5.sol\":\"RouteProcessor5\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\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 Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.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 function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\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\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\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 * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\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\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/InputStream.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\n/** @notice Simple read stream */\\nlibrary InputStream {\\n\\n /** @notice Creates stream from data\\n * @param data data\\n */\\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\\n assembly {\\n stream := mload(0x40)\\n mstore(0x40, add(stream, 64))\\n mstore(stream, data)\\n let length := mload(data)\\n mstore(add(stream, 32), add(data, length))\\n }\\n }\\n\\n /** @notice Checks if stream is not empty\\n * @param stream stream\\n */\\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\\n uint256 pos;\\n uint256 finish;\\n assembly {\\n pos := mload(stream)\\n finish := mload(add(stream, 32))\\n }\\n return pos < finish;\\n }\\n\\n /** @notice Reads uint8 from the stream\\n * @param stream stream\\n */\\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 1)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint16 from the stream\\n * @param stream stream\\n */\\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 2)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint24 from the stream\\n * @param stream stream\\n */\\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 3)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint32 from the stream\\n * @param stream stream\\n */\\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 4)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint256 from the stream\\n * @param stream stream\\n */\\n function readUint(uint256 stream) internal pure returns (uint256 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes32 from the stream\\n * @param stream stream\\n */\\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads address from the stream\\n * @param stream stream\\n */\\n function readAddress(uint256 stream) internal pure returns (address res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 20)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes from the stream\\n * @param stream stream\\n */\\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\\n assembly {\\n let pos := mload(stream)\\n res := add(pos, 32)\\n let length := mload(res)\\n mstore(stream, add(res, length))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x24e24bd0e49cbddacbf3b26bcd4bdffac63d11f3259bc05bc93c0835e8ff5300\",\"license\":\"UNLICENSED\"},\"contracts/RouteProcessor5.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '../interfaces/IUniswapV2Pair.sol';\\nimport '../interfaces/IUniswapV3Pool.sol';\\nimport '../interfaces/ITridentCLPool.sol';\\nimport '../interfaces/IBentoBoxMinimal.sol';\\nimport '../interfaces/IPool.sol';\\nimport '../interfaces/IWETH.sol';\\nimport '../interfaces/ICurve.sol';\\nimport './InputStream.sol';\\nimport './Utils.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\\n\\nuint8 constant LOCKED = 2;\\nuint8 constant NOT_LOCKED = 1;\\nuint8 constant PAUSED = 2;\\nuint8 constant NOT_PAUSED = 1;\\n\\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\nuint160 constant MIN_SQRT_RATIO = 4295128739;\\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n/// @title A route processor for the Sushi Aggregator\\n/// @author Ilya Lyalin\\ncontract RouteProcessor5 is Ownable {\\n using SafeERC20 for IERC20;\\n using Utils for IERC20;\\n using Utils for address;\\n using SafeERC20 for IERC20Permit;\\n using InputStream for uint256;\\n\\n event Route(\\n address indexed from, \\n address to, \\n address indexed tokenIn, \\n address indexed tokenOut, \\n uint256 amountIn, \\n uint256 amountOutMin,\\n uint256 amountOut\\n );\\n\\n error MinimalOutputBalanceViolation(uint256 amountOut);\\n\\n IBentoBoxMinimal public immutable bentoBox;\\n mapping (address => bool) public priviledgedUsers;\\n address private lastCalledPool;\\n\\n uint8 private unlocked = NOT_LOCKED;\\n uint8 private paused = NOT_PAUSED;\\n modifier lock() {\\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\\n unlocked = LOCKED;\\n _;\\n unlocked = NOT_LOCKED;\\n }\\n\\n modifier onlyOwnerOrPriviledgedUser() {\\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \\\"RP: caller is not the owner or a privileged user\\\");\\n _;\\n }\\n\\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\\n bentoBox = IBentoBoxMinimal(_bentoBox);\\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n\\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\\n priviledgedUsers[priviledgedUserList[i]] = true;\\n }\\n }\\n\\n function setPriviledge(address user, bool priviledge) external onlyOwner {\\n priviledgedUsers[user] = priviledge;\\n }\\n\\n function pause() external onlyOwnerOrPriviledgedUser {\\n paused = PAUSED;\\n }\\n\\n function resume() external onlyOwnerOrPriviledgedUser {\\n paused = NOT_PAUSED;\\n }\\n\\n /// @notice For native unwrapping\\n receive() external payable {}\\n\\n /// @notice Processes the route generated off-chain. Has a lock\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @param to Where to transfer output tokens\\n /// @param route Route to process\\n /// @return amountOut Actual amount of the output token\\n function processRoute(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function transferValueAndprocessRoute(\\n address transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n transferValueTo.transferNative(amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value of input tokens to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueInput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n \\n /// @notice processes the route and sends amount of output token to \\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueOutput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\\n }\\n\\n /// @notice Processes the route generated off-chain\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteInternal(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) private returns (uint256 amountOut) {\\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\\n\\n uint256 realAmountIn = amountIn;\\n {\\n uint256 step = 0;\\n uint256 stream = InputStream.createStream(route);\\n while (stream.isNotEmpty()) {\\n uint8 commandCode = stream.readUint8();\\n if (commandCode == 1) {\\n uint256 usedAmount = processMyERC20(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 2) processUserERC20(stream, amountIn);\\n else if (commandCode == 3) {\\n uint256 usedAmount = processNative(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 4) processOnePool(stream);\\n else if (commandCode == 5) processInsideBento(stream);\\n else if (commandCode == 6) applyPermit(tokenIn, stream);\\n else revert('RouteProcessor: Unknown command code');\\n ++step;\\n }\\n }\\n\\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\\n if (tokenIn != Utils.NATIVE_ADDRESS)\\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\\n \\n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\\n\\n amountOut = balanceOutFinal - balanceOutInitial;\\n\\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\\n }\\n\\n /// @notice Applies ERC-2612 permit\\n /// @param tokenIn permitted token\\n /// @param stream Streamed program\\n function applyPermit(address tokenIn, uint256 stream) private {\\n uint256 value = stream.readUint();\\n uint256 deadline = stream.readUint();\\n uint8 v = stream.readUint8();\\n bytes32 r = stream.readBytes32();\\n bytes32 s = stream.readBytes32();\\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\\n }\\n }\\n\\n /// @notice Processes native coin: call swap for all pools that swap from native coin\\n /// @param stream Streamed program\\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\\n amountTotal = address(this).balance;\\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token from this contract balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\\n address token = stream.readAddress();\\n amountTotal = IERC20(token).balanceOf(address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n \\n /// @notice Processes ERC20 token from msg.sender balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n /// @param amountTotal Amount of tokens to take from msg.sender\\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\\n address token = stream.readAddress();\\n distributeAndSwap(stream, msg.sender, token, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token for cases when the token has only one output pool\\n /// @notice In this case liquidity is already at pool balance. This is an optimization\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processOnePool(uint256 stream) private {\\n address token = stream.readAddress();\\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\\n }\\n\\n /// @notice Processes Bento tokens \\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processInsideBento(uint256 stream) private {\\n address token = stream.readAddress();\\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n\\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountTotal Total amount of tokenIn for swaps \\n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\\n uint8 num = stream.readUint8();\\n unchecked {\\n for (uint256 i = 0; i < num; ++i) {\\n uint16 share = stream.readUint16();\\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\\n amountTotal -= amount;\\n swap(stream, from, tokenIn, amount);\\n }\\n }\\n }\\n\\n /// @notice Makes swap\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 poolType = stream.readUint8();\\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\\n else revert('RouteProcessor: Unknown pool type');\\n }\\n\\n /// @notice Wraps/unwraps native token\\n /// @param stream [direction & fake, recipient, wrapToken?]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 directionAndFake = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (directionAndFake & 1 == 1) { // wrap native\\n address wrapToken = stream.readAddress();\\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\\n } else { // unwrap native\\n if (directionAndFake & 2 == 0) {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IWETH(tokenIn).withdraw(amountIn);\\n }\\n to.transferNative(amountIn);\\n }\\n }\\n\\n /// @notice Bridge/unbridge tokens to/from Bento\\n /// @param stream [direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (direction > 0) { // outside to Bento\\n // deposit to arbitrary recipient is possible only from address(bentoBox)\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\\n else {\\n // tokens already are at address(bentoBox)\\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\\n bentoBox.strategyData(tokenIn).balance -\\n bentoBox.totals(tokenIn).elastic;\\n }\\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\\n } else { // Bento to outside\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\\n }\\n }\\n\\n /// @notice UniswapV2 pool swap\\n /// @param stream [pool, direction, recipient, fee]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\\n\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\\n\\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\\n\\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\\n }\\n\\n /// @notice Trident pool swap\\n /// @param stream [pool, swapData]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bytes memory swapData = stream.readBytes();\\n\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, pool, amountIn);\\n }\\n \\n IPool(pool).swap(swapData);\\n }\\n\\n /// @notice UniswapV3 pool swap\\n /// @param stream [pool, direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bool zeroForOne = stream.readUint8() > 0;\\n address recipient = stream.readAddress();\\n\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\\n\\n lastCalledPool = pool;\\n IUniswapV3Pool(pool).swap(\\n recipient,\\n zeroForOne,\\n int256(amountIn),\\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\\n abi.encode(tokenIn)\\n );\\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) public {\\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\\n \\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n (address tokenIn) = abi.decode(data, (address));\\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\\n function algebraSwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\\n function pancakeV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 poolType = stream.readUint8();\\n int128 fromIndex = int8(stream.readUint8());\\n int128 toIndex = int8(stream.readUint8());\\n address to = stream.readAddress();\\n address tokenOut = stream.readAddress();\\n\\n uint256 amountOut;\\n if (tokenIn == Utils.NATIVE_ADDRESS) {\\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\\n } else {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IERC20(tokenIn).approveSafe(pool, amountIn);\\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n else {\\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\\n amountOut = balanceAfter - balanceBefore;\\n }\\n }\\n\\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\\n }\\n}\\n\",\"keccak256\":\"0xcd53a7f473f1847d44c42777a194203cbff02b8c761cb2935402401f57c918a2\",\"license\":\"UNLICENSED\"},\"contracts/Utils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\n\\nlibrary Utils {\\n using SafeERC20 for IERC20;\\n\\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n /**\\n * @dev returns user's balance of token (or native)\\n */\\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\\n if (token == NATIVE_ADDRESS) return address(user).balance;\\n else return IERC20(token).balanceOf(user);\\n }\\n\\n /**\\n * @dev transfers native with correct revert bubble up\\n */\\n function transferNative(address to, uint256 amount) internal {\\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\\n if (!success) {\\n assembly {\\n revert(add(32, returnBytes), mload(returnBytes))\\n }\\n }\\n }\\n\\n /**\\n * @dev transfers ERC20 or native\\n */\\n function transferAny(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\\n else IERC20(token).safeTransfer(to, amount);\\n }\\n\\n /**\\n * @dev transfers from ERC20 or transfers native\\n */\\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n (bool success, bytes memory data) = address(token).call(\\n abi.encodeWithSelector(token.approve.selector, spender, amount)\\n );\\n return success && (data.length == 0 || abi.decode(data, (bool)));\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \\n * current allowance are not zero simultaniously (USDT for example). \\n * In second case it tries to set allowance to 0, and then back to amount.\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n return approveStable(token, spender, amount) \\n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\\n }\\n}\\n\",\"keccak256\":\"0x8c8439edc00b403abd3f34be75a06b1fe71152644ae9f19488af596bbc534ffe\",\"license\":\"UNLICENSED\"},\"interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\nstruct StrategyData {\\n uint64 strategyStartDate;\\n uint64 targetPercentage;\\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n function strategyData(address token) external view returns (StrategyData memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0x0c12eba7a5b9d22d37ab8883fe22d6a312a90682809dbd11c43f8e6ceaff73bf\",\"license\":\"UNLICENSED\"},\"interfaces/ICurve.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\ninterface ICurve {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\\n}\\n\\ninterface ICurveLegacy {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\\n}\\n\\n\",\"keccak256\":\"0x3d4940b3583e06dde20f12e92d2f6ac573b3f64bdaa1e8f480656a3763852518\",\"license\":\"UNLICENSED\"},\"interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/ITridentCLPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface ITridentCLPool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bool unwrapBento,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x572376b80c86a94692b0e27e6e63790b763295e32ba1f956c1d331fc1296de8d\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IUniswapV2Pair.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Pair {\\n event Approval(address indexed owner, address indexed spender, uint value);\\n event Transfer(address indexed from, address indexed to, uint value);\\n\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function allowance(address owner, address spender) external view returns (uint);\\n\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address to, uint value) external returns (bool);\\n function transferFrom(address from, address to, uint value) external returns (bool);\\n\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n function nonces(address owner) external view returns (uint);\\n\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n event Mint(address indexed sender, uint amount0, uint amount1);\\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\\n event Swap(\\n address indexed sender,\\n uint amount0In,\\n uint amount1In,\\n uint amount0Out,\\n uint amount1Out,\\n address indexed to\\n );\\n event Sync(uint112 reserve0, uint112 reserve1);\\n\\n function MINIMUM_LIQUIDITY() external pure returns (uint);\\n function factory() external view returns (address);\\n function token0() external view returns (address);\\n function token1() external view returns (address);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\\n function price0CumulativeLast() external view returns (uint);\\n function price1CumulativeLast() external view returns (uint);\\n function kLast() external view returns (uint);\\n\\n function mint(address to) external returns (uint liquidity);\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function skim(address to) external;\\n function sync() external;\\n\\n function initialize(address, address) external;\\n}\",\"keccak256\":\"0x08f9a63b34855eec941be8d36a04424f1a1725a2c030373fcef3afeb480ca385\",\"license\":\"GPL-3.0\"},\"interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IUniswapV3Pool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x2a4d7c6120e613f0e95d4dc8c650efb9b59e3c25c64e3e5c0a379281500f0a79\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IWETH.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0xae8529ae159f784b90fdcd0629bd03bf7b68accc81edccac53357ad08406a378\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}", + "bytecode": "0x60a06040526002805461ffff60a01b191661010160a01b1790553480156200002657600080fd5b50604051620040a3380380620040a383398101604081905262000049916200016e565b6200005433620000eb565b6001600160a01b038216608052600280546001600160a01b031916600117905560005b8151811015620000e25760018060008484815181106200009b576200009b62000257565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000d9816200026d565b91505062000077565b50505062000297565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200015357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200018257600080fd5b6200018d836200013b565b602084810151919350906001600160401b0380821115620001ad57600080fd5b818601915086601f830112620001c257600080fd5b815181811115620001d757620001d762000158565b8060051b604051601f19603f83011681018181108582111715620001ff57620001ff62000158565b6040529182528482019250838101850191898311156200021e57600080fd5b938501935b82851015620002475762000237856200013b565b8452938501939285019262000223565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200029057634e487b7160e01b600052601160045260246000fd5b5060010190565b608051613da3620003006000396000818161018d01528181611798015281816127380152818161279d01528181612807015281816128cc0152818161297901528181612a5d01528181612b6401528181612c1001528181612cdf0152612df10152613da36000f3fe6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "deployedBytecode": "0x6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "devdoc": { + "author": "Ilya Lyalin", + "kind": "dev", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IAlgebraPoolActions#swap call" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the PancakeV3Pool#swap call" + } + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "route": "Route to process", + "to": "Where to transfer output tokens", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IUniswapV3PoolActions#swap call" + } + } + }, + "title": "A route processor for the Sushi Aggregator", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IAlgebraPool#swap." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via PancakeV3Pool#swap." + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "notice": "Processes the route generated off-chain. Has a lock" + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value of input tokens to and then processes the route" + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "processes the route and sends amount of output token to " + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value to and then processes the route" + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 1060, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "priviledgedUsers", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 1062, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "lastCalledPool", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 1065, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "unlocked", + "offset": 20, + "slot": "2", + "type": "t_uint8" + }, + { + "astId": 1068, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "paused", + "offset": 21, + "slot": "2", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/zetachain/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json b/protocols/route-processor/deployments/zetachain/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json new file mode 100644 index 0000000000..01826e7b93 --- /dev/null +++ b/protocols/route-processor/deployments/zetachain/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json @@ -0,0 +1,80 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" + }, + "contracts/InputStream.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" + }, + "contracts/RouteProcessor5.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" + }, + "contracts/Utils.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "interfaces/IBentoBoxMinimal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" + }, + "interfaces/ICurve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" + }, + "interfaces/IPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" + }, + "interfaces/ITridentCLPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file From 582b44113e0d1a81e0df5e27fd592b7e504e791b Mon Sep 17 00:00:00 2001 From: 0xMasayoshi <0xMasayoshi@protonmail.com> Date: Tue, 30 Jul 2024 01:48:13 +0700 Subject: [PATCH 009/125] chore: change skale rpc for maintenance --- packages/sushi/src/config/viem.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/sushi/src/config/viem.ts b/packages/sushi/src/config/viem.ts index 5833d0e2e3..3294040132 100644 --- a/packages/sushi/src/config/viem.ts +++ b/packages/sushi/src/config/viem.ts @@ -605,7 +605,7 @@ export const publicTransports = { `https://lb.drpc.org/ogrpc?network=blast&dkey=${drpcId}`, ), [ChainId.SKALE_EUROPA]: http( - 'https://elated-tan-skat-archive-backup.skalenodes.com:10072', + 'https://elated-tan-skat-indexer-backup.skalenodes.com:10072', ), [ChainId.ROOTSTOCK]: http( rskId From 5b4d88a4fd61a64d94b0adc6e88874effabf7762 Mon Sep 17 00:00:00 2001 From: 0xMasayoshi <0xMasayoshi@protonmail.com> Date: Wed, 31 Jul 2024 02:19:43 +0700 Subject: [PATCH 010/125] chore: update skale rpc endpoint --- packages/sushi/src/config/viem.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/sushi/src/config/viem.ts b/packages/sushi/src/config/viem.ts index 738be59118..bebc1e73dc 100644 --- a/packages/sushi/src/config/viem.ts +++ b/packages/sushi/src/config/viem.ts @@ -605,7 +605,7 @@ export const publicTransports = { `https://lb.drpc.org/ogrpc?network=blast&dkey=${drpcId}`, ), [ChainId.SKALE_EUROPA]: http( - 'https://elated-tan-skat-indexer-backup.skalenodes.com:10072', + 'https://elated-tan-skat-indexer.skalenodes.com:10072', ), [ChainId.ROOTSTOCK]: http( rskId From 54215902046e9fe6b6ed9be4af95cba9d1a43b37 Mon Sep 17 00:00:00 2001 From: 0xMasayoshi <0xMasayoshi@protonmail.com> Date: Thu, 1 Aug 2024 11:43:10 +0700 Subject: [PATCH 011/125] chore: update skale RP5 deployment files --- .../skale-europa/RouteProcessor5.json | 36 +++---- .../9252879aaeb02fabe759ce8768addec4.json | 98 +++++++++++++++++++ .../e556d43a3caf4f1fb4f12d632d103b28.json | 80 --------------- 3 files changed, 116 insertions(+), 98 deletions(-) create mode 100644 protocols/route-processor/deployments/skale-europa/solcInputs/9252879aaeb02fabe759ce8768addec4.json delete mode 100644 protocols/route-processor/deployments/skale-europa/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json diff --git a/protocols/route-processor/deployments/skale-europa/RouteProcessor5.json b/protocols/route-processor/deployments/skale-europa/RouteProcessor5.json index 28c139c06f..687a7a983a 100644 --- a/protocols/route-processor/deployments/skale-europa/RouteProcessor5.json +++ b/protocols/route-processor/deployments/skale-europa/RouteProcessor5.json @@ -1,5 +1,5 @@ { - "address": "0xd40535cF25cD9E8Ed5E7Ee57534F534F6fCc95b1", + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", "abi": [ { "inputs": [ @@ -473,33 +473,33 @@ "type": "receive" } ], - "transactionHash": "0xa71d0378be1797e89efa438cdce7c99a60e4eaa4daf9c28944f6334ec3a59caa", + "transactionHash": "0x840710c63c7a2397e4e5a411747fdf772fc515e0cc5f2e6490303e6d7e406a06", "receipt": { "to": "0x0000000000000000000000000000000000000000", - "from": "0x19f012FB3A5610B076b4Db95d1EE4E3dC3AA5A9C", - "contractAddress": "0xd40535cF25cD9E8Ed5E7Ee57534F534F6fCc95b1", + "from": "0x282607716D9B4fDD0B094d5864fac56313f5e665", + "contractAddress": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", "transactionIndex": 0, "gasUsed": "3491833", - "logsBloom": "0x00000000200000000000000000000000000000000008000000800000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000004000400000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x30466f4f115b0fbeb812313f9b4bec9ada070ecd2f6aa6a24dda9e3c42f7b0ed", - "transactionHash": "0xa71d0378be1797e89efa438cdce7c99a60e4eaa4daf9c28944f6334ec3a59caa", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000020000000000000000000000000000000000000001000000000000000000000000000000000000000000040000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000000000000000000000000000", + "blockHash": "0xcd827be95a199d802ea9a3bebc0e1fda05d53089a9e8b2986570ca2af53c4eb6", + "transactionHash": "0x840710c63c7a2397e4e5a411747fdf772fc515e0cc5f2e6490303e6d7e406a06", "logs": [ { "transactionIndex": 0, - "blockNumber": 6013321, - "transactionHash": "0xa71d0378be1797e89efa438cdce7c99a60e4eaa4daf9c28944f6334ec3a59caa", - "address": "0xd40535cF25cD9E8Ed5E7Ee57534F534F6fCc95b1", + "blockNumber": 6035212, + "transactionHash": "0x840710c63c7a2397e4e5a411747fdf772fc515e0cc5f2e6490303e6d7e406a06", + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", "topics": [ "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000019f012fb3a5610b076b4db95d1ee4e3dc3aa5a9c" + "0x000000000000000000000000282607716d9b4fdd0b094d5864fac56313f5e665" ], "data": "0x", "logIndex": 0, - "blockHash": "0x30466f4f115b0fbeb812313f9b4bec9ada070ecd2f6aa6a24dda9e3c42f7b0ed" + "blockHash": "0xcd827be95a199d802ea9a3bebc0e1fda05d53089a9e8b2986570ca2af53c4eb6" } ], - "blockNumber": 6013321, + "blockNumber": 6035212, "cumulativeGasUsed": "3491833", "status": 1, "byzantium": true @@ -509,7 +509,7 @@ [] ], "numDeployments": 1, - "solcInputHash": "e556d43a3caf4f1fb4f12d632d103b28", + "solcInputHash": "9252879aaeb02fabe759ce8768addec4", "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bentoBox\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"priviledgedUserList\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"MinimalOutputBalanceViolation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"Route\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"algebraSwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"pancakeV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"priviledgedUsers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"priviledge\",\"type\":\"bool\"}],\"name\":\"setPriviledge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"transferValueAndprocessRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"Ilya Lyalin\",\"kind\":\"dev\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IAlgebraPoolActions#swap call\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the PancakeV3Pool#swap call\"}},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"route\":\"Route to process\",\"to\":\"Where to transfer output tokens\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IUniswapV3PoolActions#swap call\"}}},\"title\":\"A route processor for the Sushi Aggregator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\"},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Processes the route generated off-chain. Has a lock\"},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value of input tokens to and then processes the route\"},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"processes the route and sends amount of output token to \"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value to and then processes the route\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RouteProcessor5.sol\":\"RouteProcessor5\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\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 Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.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 function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\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\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\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 * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\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\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/InputStream.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\n/** @notice Simple read stream */\\nlibrary InputStream {\\n\\n /** @notice Creates stream from data\\n * @param data data\\n */\\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\\n assembly {\\n stream := mload(0x40)\\n mstore(0x40, add(stream, 64))\\n mstore(stream, data)\\n let length := mload(data)\\n mstore(add(stream, 32), add(data, length))\\n }\\n }\\n\\n /** @notice Checks if stream is not empty\\n * @param stream stream\\n */\\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\\n uint256 pos;\\n uint256 finish;\\n assembly {\\n pos := mload(stream)\\n finish := mload(add(stream, 32))\\n }\\n return pos < finish;\\n }\\n\\n /** @notice Reads uint8 from the stream\\n * @param stream stream\\n */\\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 1)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint16 from the stream\\n * @param stream stream\\n */\\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 2)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint24 from the stream\\n * @param stream stream\\n */\\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 3)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint32 from the stream\\n * @param stream stream\\n */\\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 4)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint256 from the stream\\n * @param stream stream\\n */\\n function readUint(uint256 stream) internal pure returns (uint256 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes32 from the stream\\n * @param stream stream\\n */\\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads address from the stream\\n * @param stream stream\\n */\\n function readAddress(uint256 stream) internal pure returns (address res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 20)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes from the stream\\n * @param stream stream\\n */\\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\\n assembly {\\n let pos := mload(stream)\\n res := add(pos, 32)\\n let length := mload(res)\\n mstore(stream, add(res, length))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x24e24bd0e49cbddacbf3b26bcd4bdffac63d11f3259bc05bc93c0835e8ff5300\",\"license\":\"UNLICENSED\"},\"contracts/RouteProcessor5.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '../interfaces/IUniswapV2Pair.sol';\\nimport '../interfaces/IUniswapV3Pool.sol';\\nimport '../interfaces/ITridentCLPool.sol';\\nimport '../interfaces/IBentoBoxMinimal.sol';\\nimport '../interfaces/IPool.sol';\\nimport '../interfaces/IWETH.sol';\\nimport '../interfaces/ICurve.sol';\\nimport './InputStream.sol';\\nimport './Utils.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\\n\\nuint8 constant LOCKED = 2;\\nuint8 constant NOT_LOCKED = 1;\\nuint8 constant PAUSED = 2;\\nuint8 constant NOT_PAUSED = 1;\\n\\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\nuint160 constant MIN_SQRT_RATIO = 4295128739;\\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n/// @title A route processor for the Sushi Aggregator\\n/// @author Ilya Lyalin\\ncontract RouteProcessor5 is Ownable {\\n using SafeERC20 for IERC20;\\n using Utils for IERC20;\\n using Utils for address;\\n using SafeERC20 for IERC20Permit;\\n using InputStream for uint256;\\n\\n event Route(\\n address indexed from, \\n address to, \\n address indexed tokenIn, \\n address indexed tokenOut, \\n uint256 amountIn, \\n uint256 amountOutMin,\\n uint256 amountOut\\n );\\n\\n error MinimalOutputBalanceViolation(uint256 amountOut);\\n\\n IBentoBoxMinimal public immutable bentoBox;\\n mapping (address => bool) public priviledgedUsers;\\n address private lastCalledPool;\\n\\n uint8 private unlocked = NOT_LOCKED;\\n uint8 private paused = NOT_PAUSED;\\n modifier lock() {\\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\\n unlocked = LOCKED;\\n _;\\n unlocked = NOT_LOCKED;\\n }\\n\\n modifier onlyOwnerOrPriviledgedUser() {\\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \\\"RP: caller is not the owner or a privileged user\\\");\\n _;\\n }\\n\\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\\n bentoBox = IBentoBoxMinimal(_bentoBox);\\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n\\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\\n priviledgedUsers[priviledgedUserList[i]] = true;\\n }\\n }\\n\\n function setPriviledge(address user, bool priviledge) external onlyOwner {\\n priviledgedUsers[user] = priviledge;\\n }\\n\\n function pause() external onlyOwnerOrPriviledgedUser {\\n paused = PAUSED;\\n }\\n\\n function resume() external onlyOwnerOrPriviledgedUser {\\n paused = NOT_PAUSED;\\n }\\n\\n /// @notice For native unwrapping\\n receive() external payable {}\\n\\n /// @notice Processes the route generated off-chain. Has a lock\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @param to Where to transfer output tokens\\n /// @param route Route to process\\n /// @return amountOut Actual amount of the output token\\n function processRoute(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function transferValueAndprocessRoute(\\n address transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n transferValueTo.transferNative(amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value of input tokens to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueInput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n \\n /// @notice processes the route and sends amount of output token to \\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueOutput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\\n }\\n\\n /// @notice Processes the route generated off-chain\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteInternal(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) private returns (uint256 amountOut) {\\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\\n\\n uint256 realAmountIn = amountIn;\\n {\\n uint256 step = 0;\\n uint256 stream = InputStream.createStream(route);\\n while (stream.isNotEmpty()) {\\n uint8 commandCode = stream.readUint8();\\n if (commandCode == 1) {\\n uint256 usedAmount = processMyERC20(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 2) processUserERC20(stream, amountIn);\\n else if (commandCode == 3) {\\n uint256 usedAmount = processNative(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 4) processOnePool(stream);\\n else if (commandCode == 5) processInsideBento(stream);\\n else if (commandCode == 6) applyPermit(tokenIn, stream);\\n else revert('RouteProcessor: Unknown command code');\\n ++step;\\n }\\n }\\n\\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\\n if (tokenIn != Utils.NATIVE_ADDRESS)\\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\\n \\n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\\n\\n amountOut = balanceOutFinal - balanceOutInitial;\\n\\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\\n }\\n\\n /// @notice Applies ERC-2612 permit\\n /// @param tokenIn permitted token\\n /// @param stream Streamed program\\n function applyPermit(address tokenIn, uint256 stream) private {\\n uint256 value = stream.readUint();\\n uint256 deadline = stream.readUint();\\n uint8 v = stream.readUint8();\\n bytes32 r = stream.readBytes32();\\n bytes32 s = stream.readBytes32();\\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\\n }\\n }\\n\\n /// @notice Processes native coin: call swap for all pools that swap from native coin\\n /// @param stream Streamed program\\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\\n amountTotal = address(this).balance;\\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token from this contract balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\\n address token = stream.readAddress();\\n amountTotal = IERC20(token).balanceOf(address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n \\n /// @notice Processes ERC20 token from msg.sender balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n /// @param amountTotal Amount of tokens to take from msg.sender\\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\\n address token = stream.readAddress();\\n distributeAndSwap(stream, msg.sender, token, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token for cases when the token has only one output pool\\n /// @notice In this case liquidity is already at pool balance. This is an optimization\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processOnePool(uint256 stream) private {\\n address token = stream.readAddress();\\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\\n }\\n\\n /// @notice Processes Bento tokens \\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processInsideBento(uint256 stream) private {\\n address token = stream.readAddress();\\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n\\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountTotal Total amount of tokenIn for swaps \\n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\\n uint8 num = stream.readUint8();\\n unchecked {\\n for (uint256 i = 0; i < num; ++i) {\\n uint16 share = stream.readUint16();\\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\\n amountTotal -= amount;\\n swap(stream, from, tokenIn, amount);\\n }\\n }\\n }\\n\\n /// @notice Makes swap\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 poolType = stream.readUint8();\\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\\n else revert('RouteProcessor: Unknown pool type');\\n }\\n\\n /// @notice Wraps/unwraps native token\\n /// @param stream [direction & fake, recipient, wrapToken?]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 directionAndFake = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (directionAndFake & 1 == 1) { // wrap native\\n address wrapToken = stream.readAddress();\\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\\n } else { // unwrap native\\n if (directionAndFake & 2 == 0) {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IWETH(tokenIn).withdraw(amountIn);\\n }\\n to.transferNative(amountIn);\\n }\\n }\\n\\n /// @notice Bridge/unbridge tokens to/from Bento\\n /// @param stream [direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (direction > 0) { // outside to Bento\\n // deposit to arbitrary recipient is possible only from address(bentoBox)\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\\n else {\\n // tokens already are at address(bentoBox)\\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\\n bentoBox.strategyData(tokenIn).balance -\\n bentoBox.totals(tokenIn).elastic;\\n }\\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\\n } else { // Bento to outside\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\\n }\\n }\\n\\n /// @notice UniswapV2 pool swap\\n /// @param stream [pool, direction, recipient, fee]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\\n\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\\n\\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\\n\\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\\n }\\n\\n /// @notice Trident pool swap\\n /// @param stream [pool, swapData]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bytes memory swapData = stream.readBytes();\\n\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, pool, amountIn);\\n }\\n \\n IPool(pool).swap(swapData);\\n }\\n\\n /// @notice UniswapV3 pool swap\\n /// @param stream [pool, direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bool zeroForOne = stream.readUint8() > 0;\\n address recipient = stream.readAddress();\\n\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\\n\\n lastCalledPool = pool;\\n IUniswapV3Pool(pool).swap(\\n recipient,\\n zeroForOne,\\n int256(amountIn),\\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\\n abi.encode(tokenIn)\\n );\\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) public {\\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\\n \\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n (address tokenIn) = abi.decode(data, (address));\\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\\n function algebraSwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\\n function pancakeV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 poolType = stream.readUint8();\\n int128 fromIndex = int8(stream.readUint8());\\n int128 toIndex = int8(stream.readUint8());\\n address to = stream.readAddress();\\n address tokenOut = stream.readAddress();\\n\\n uint256 amountOut;\\n if (tokenIn == Utils.NATIVE_ADDRESS) {\\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\\n } else {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IERC20(tokenIn).approveSafe(pool, amountIn);\\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n else {\\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\\n amountOut = balanceAfter - balanceBefore;\\n }\\n }\\n\\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\\n }\\n}\\n\",\"keccak256\":\"0xcd53a7f473f1847d44c42777a194203cbff02b8c761cb2935402401f57c918a2\",\"license\":\"UNLICENSED\"},\"contracts/Utils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\n\\nlibrary Utils {\\n using SafeERC20 for IERC20;\\n\\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n /**\\n * @dev returns user's balance of token (or native)\\n */\\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\\n if (token == NATIVE_ADDRESS) return address(user).balance;\\n else return IERC20(token).balanceOf(user);\\n }\\n\\n /**\\n * @dev transfers native with correct revert bubble up\\n */\\n function transferNative(address to, uint256 amount) internal {\\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\\n if (!success) {\\n assembly {\\n revert(add(32, returnBytes), mload(returnBytes))\\n }\\n }\\n }\\n\\n /**\\n * @dev transfers ERC20 or native\\n */\\n function transferAny(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\\n else IERC20(token).safeTransfer(to, amount);\\n }\\n\\n /**\\n * @dev transfers from ERC20 or transfers native\\n */\\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n (bool success, bytes memory data) = address(token).call(\\n abi.encodeWithSelector(token.approve.selector, spender, amount)\\n );\\n return success && (data.length == 0 || abi.decode(data, (bool)));\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \\n * current allowance are not zero simultaniously (USDT for example). \\n * In second case it tries to set allowance to 0, and then back to amount.\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n return approveStable(token, spender, amount) \\n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\\n }\\n}\\n\",\"keccak256\":\"0x8c8439edc00b403abd3f34be75a06b1fe71152644ae9f19488af596bbc534ffe\",\"license\":\"UNLICENSED\"},\"interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\nstruct StrategyData {\\n uint64 strategyStartDate;\\n uint64 targetPercentage;\\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n function strategyData(address token) external view returns (StrategyData memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0x0c12eba7a5b9d22d37ab8883fe22d6a312a90682809dbd11c43f8e6ceaff73bf\",\"license\":\"UNLICENSED\"},\"interfaces/ICurve.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\ninterface ICurve {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\\n}\\n\\ninterface ICurveLegacy {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\\n}\\n\\n\",\"keccak256\":\"0x3d4940b3583e06dde20f12e92d2f6ac573b3f64bdaa1e8f480656a3763852518\",\"license\":\"UNLICENSED\"},\"interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/ITridentCLPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface ITridentCLPool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bool unwrapBento,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x572376b80c86a94692b0e27e6e63790b763295e32ba1f956c1d331fc1296de8d\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IUniswapV2Pair.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Pair {\\n event Approval(address indexed owner, address indexed spender, uint value);\\n event Transfer(address indexed from, address indexed to, uint value);\\n\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function allowance(address owner, address spender) external view returns (uint);\\n\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address to, uint value) external returns (bool);\\n function transferFrom(address from, address to, uint value) external returns (bool);\\n\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n function nonces(address owner) external view returns (uint);\\n\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n event Mint(address indexed sender, uint amount0, uint amount1);\\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\\n event Swap(\\n address indexed sender,\\n uint amount0In,\\n uint amount1In,\\n uint amount0Out,\\n uint amount1Out,\\n address indexed to\\n );\\n event Sync(uint112 reserve0, uint112 reserve1);\\n\\n function MINIMUM_LIQUIDITY() external pure returns (uint);\\n function factory() external view returns (address);\\n function token0() external view returns (address);\\n function token1() external view returns (address);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\\n function price0CumulativeLast() external view returns (uint);\\n function price1CumulativeLast() external view returns (uint);\\n function kLast() external view returns (uint);\\n\\n function mint(address to) external returns (uint liquidity);\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function skim(address to) external;\\n function sync() external;\\n\\n function initialize(address, address) external;\\n}\",\"keccak256\":\"0x08f9a63b34855eec941be8d36a04424f1a1725a2c030373fcef3afeb480ca385\",\"license\":\"GPL-3.0\"},\"interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IUniswapV3Pool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x2a4d7c6120e613f0e95d4dc8c650efb9b59e3c25c64e3e5c0a379281500f0a79\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IWETH.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0xae8529ae159f784b90fdcd0629bd03bf7b68accc81edccac53357ad08406a378\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}", "bytecode": "0x60a06040526002805461ffff60a01b191661010160a01b1790553480156200002657600080fd5b50604051620040a3380380620040a383398101604081905262000049916200016e565b6200005433620000eb565b6001600160a01b038216608052600280546001600160a01b031916600117905560005b8151811015620000e25760018060008484815181106200009b576200009b62000257565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000d9816200026d565b91505062000077565b50505062000297565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200015357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200018257600080fd5b6200018d836200013b565b602084810151919350906001600160401b0380821115620001ad57600080fd5b818601915086601f830112620001c257600080fd5b815181811115620001d757620001d762000158565b8060051b604051601f19603f83011681018181108582111715620001ff57620001ff62000158565b6040529182528482019250838101850191898311156200021e57600080fd5b938501935b82851015620002475762000237856200013b565b8452938501939285019262000223565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200029057634e487b7160e01b600052601160045260246000fd5b5060010190565b608051613da3620003006000396000818161018d01528181611798015281816127380152818161279d01528181612807015281816128cc0152818161297901528181612a5d01528181612b6401528181612c1001528181612cdf0152612df10152613da36000f3fe6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", "deployedBytecode": "0x6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", @@ -644,7 +644,7 @@ "type": "t_address" }, { - "astId": 1060, + "astId": 8573, "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", "label": "priviledgedUsers", "offset": 0, @@ -652,7 +652,7 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1062, + "astId": 8575, "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", "label": "lastCalledPool", "offset": 0, @@ -660,7 +660,7 @@ "type": "t_address" }, { - "astId": 1065, + "astId": 8578, "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", "label": "unlocked", "offset": 20, @@ -668,7 +668,7 @@ "type": "t_uint8" }, { - "astId": 1068, + "astId": 8581, "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", "label": "paused", "offset": 21, diff --git a/protocols/route-processor/deployments/skale-europa/solcInputs/9252879aaeb02fabe759ce8768addec4.json b/protocols/route-processor/deployments/skale-europa/solcInputs/9252879aaeb02fabe759ce8768addec4.json new file mode 100644 index 0000000000..c6762a8dc1 --- /dev/null +++ b/protocols/route-processor/deployments/skale-europa/solcInputs/9252879aaeb02fabe759ce8768addec4.json @@ -0,0 +1,98 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" + }, + "contracts/Approve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\n\nlibrary Approve {\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "contracts/InputStream.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" + }, + "contracts/RouteProcessor.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport './InputStream.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\naddress constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Okavango\ncontract RouteProcessor {\n using SafeERC20 for IERC20;\n using InputStream for uint256;\n\n IBentoBoxMinimal public immutable bentoBox;\n\n uint private unlocked = 1;\n modifier lock() {\n require(unlocked == 1, 'RouteProcessor is locked');\n unlocked = 2;\n _;\n unlocked = 1;\n }\n\n constructor(address _bentoBox) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n (bool success, bytes memory returnBytes) = transferValueTo.call{value: amountValueTransfer}('');\n require(success, string(abi.encodePacked(returnBytes)));\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 amountInAcc = 0;\n uint256 balanceInitial = tokenOut == NATIVE_ADDRESS ? \n address(to).balance : IERC20(tokenOut).balanceOf(to);\n\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode < 20) {\n if (commandCode == 10)\n swapUniswapPool(stream); // Sushi/Uniswap pool swap\n else if (commandCode == 4)\n distributeERC20Shares(stream); // distribute ERC20 tokens from this router to pools\n else if (commandCode == 3)\n amountInAcc += distributeERC20Amounts(stream, tokenIn); // initial distribution\n else if (commandCode == 5)\n amountInAcc += wrapAndDistributeERC20Amounts(stream); // wrap natives and initial distribution \n else if (commandCode == 6) \n unwrapNative(to, stream);\n else if (commandCode == 7)\n amountInAcc += distributeERC20AmountsFromRP(stream, tokenIn); // initial distribution\n else revert('Unknown command code');\n } else if (commandCode < 24) {\n if (commandCode == 20) bentoDepositAmountFromBento(stream, tokenIn);\n else if (commandCode == 21) swapTrident(stream);\n else if (commandCode == 23) bentoWithdrawShareFromRP(stream, tokenIn);\n else revert('Unknown command code');\n } else {\n if (commandCode == 24) amountInAcc += distributeBentoShares(stream, tokenIn);\n else if (commandCode == 25) distributeBentoPortions(stream);\n else if (commandCode == 26) bentoDepositAllFromBento(stream);\n else if (commandCode == 27) bentoWithdrawAllFromRP(stream);\n else revert('Unknown command code');\n }\n }\n\n require(amountInAcc == amountIn, 'Wrong amountIn value');\n uint256 balanceFinal = tokenOut == NATIVE_ADDRESS ? \n address(to).balance : IERC20(tokenOut).balanceOf(to);\n require(balanceFinal >= balanceInitial + amountOutMin, 'Minimal ouput balance violation');\n\n amountOut = balanceFinal - balanceInitial;\n }\n\n /// @notice Transfers input tokens sent to BentoBox to a pool\n /// @notice Expected to be called for initial liquidity transfer from user to BentoBox, so we know exact amounts\n /// @param stream [Pool, Amount]. Pool into which an amount of tokens will be transferred\n /// @param token Address of the token to transfer\n function bentoDepositAmountFromBento(uint256 stream, address token) private {\n address to = stream.readAddress();\n uint256 amount = stream.readUint();\n bentoBox.deposit(token, address(bentoBox), to, amount, 0);\n }\n\n /// @notice Transfers all available input tokens from BentoBox to a pool\n /// @param stream [Pool, Token]. Pool into which all tokens will be transferred \n function bentoDepositAllFromBento(uint256 stream) private {\n address to = stream.readAddress();\n address token = stream.readAddress();\n\n uint256 amount = IERC20(token).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(token).balance -\n bentoBox.totals(token).elastic;\n bentoBox.deposit(token, address(bentoBox), to, amount, 0);\n }\n\n /// @notice Withdraws BentoBox tokens from BentoBox to an address\n /// @param stream [To, Amount]. Destination where an amount of token will be transferred\n /// @param token Token to transfer\n function bentoWithdrawShareFromRP(uint256 stream, address token) private {\n address to = stream.readAddress();\n uint256 amount = stream.readUint();\n bentoBox.withdraw(token, address(this), to, amount, 0);\n }\n\n /// @notice Withdraws all available BentoBox tokens from BentoBox to an address\n /// @param stream [Token, To]. Token which will be transferred to a destination\n function bentoWithdrawAllFromRP(uint256 stream) private {\n address token = stream.readAddress();\n address to = stream.readAddress();\n uint256 amount = bentoBox.balanceOf(token, address(this));\n bentoBox.withdraw(token, address(this), to, 0, amount);\n }\n\n /// @notice Performs a Trident pool swap\n /// @param stream [Pool, SwapData]. Pool against a swap defined by SwapData will be executed\n function swapTrident(uint256 stream) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n IPool(pool).swap(swapData);\n }\n\n /// @notice Performs a Sushi/UniswapV2 pool swap\n /// @param stream [Pool, TokenIn, Direction, To]\n /// @return amountOut Amount of the output token\n function swapUniswapPool(uint256 stream) private returns (uint256 amountOut) {\n address pool = stream.readAddress();\n address tokenIn = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n\n uint256 amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn;\n uint256 amountInWithFee = amountIn * 997;\n amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Distributes input ERC20 tokens from msg.sender to addresses. Tokens should be approved\n /// @notice Expected to be called for initial liquidity transfer from the user to pools, so we know exact amounts\n /// @param stream [ArrayLength, ...[To, Amount][]]. An array of destinations and token amounts\n /// @param token Token to distribute\n /// @return amountTotal Total amount distributed\n function distributeERC20Amounts(uint256 stream, address token) private returns (uint256 amountTotal) {\n uint8 num = stream.readUint8();\n amountTotal = 0;\n for (uint256 i = 0; i < num; ++i) {\n address to = stream.readAddress();\n uint256 amount = stream.readUint();\n amountTotal += amount;\n IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n }\n\n /// @notice Distributes input ERC20 tokens from this contract to addresses. Tokens should be approved\n /// @notice Expected to be called for initial liquidity transfer from the user to pools, so we know exact amounts\n /// @param stream [ArrayLength, ...[To, Amount][]]. An array of destinations and token amounts\n /// @param token Token to distribute\n /// @return amountTotal Total amount distributed\n function distributeERC20AmountsFromRP(uint256 stream, address token) private returns (uint256 amountTotal) {\n uint8 num = stream.readUint8();\n amountTotal = 0;\n for (uint256 i = 0; i < num; ++i) {\n address to = stream.readAddress();\n uint256 amount = stream.readUint();\n amountTotal += amount;\n IERC20(token).safeTransfer(to, amount);\n }\n }\n\n /// @notice Wraps all native inputs and distributes wrapped ERC20 tokens from RouteProcessor to addresses\n /// @notice Expected to be called for initial liquidity transfer from the user to pools, so we know exact amounts\n /// @param stream [WrapToken, ArrayLength, ...[To, Amount][]]. An array of destinations and token amounts\n /// @return amountTotal Total amount distributed\n function wrapAndDistributeERC20Amounts(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n IWETH(token).deposit{value: address(this).balance}();\n uint8 num = stream.readUint8();\n amountTotal = 0;\n for (uint256 i = 0; i < num; ++i) {\n address to = stream.readAddress();\n uint256 amount = stream.readUint();\n amountTotal += amount;\n IERC20(token).safeTransfer(to, amount);\n }\n require(address(this).balance == 0, \"RouteProcessor: invalid input amount\");\n }\n\n /// @notice Distributes input BentoBox tokens from msg.sender to addresses. Tokens should be approved\n /// @notice Expected to be called for initial liquidity transfer from the user to pools, so we know exact amounts\n /// @param stream [ArrayLength, ...[To, ShareAmount][]]. An array of destinations and token share amounts\n /// @param token Token to distribute\n /// @return sharesTotal Total shares distributed\n function distributeBentoShares(uint256 stream, address token) private returns (uint256 sharesTotal) {\n uint8 num = stream.readUint8();\n sharesTotal = 0;\n for (uint256 i = 0; i < num; ++i) {\n address to = stream.readAddress();\n uint256 share = stream.readUint();\n sharesTotal += share;\n bentoBox.transfer(token, msg.sender, to, share);\n }\n }\n\n /// @notice Distributes ERC20 tokens from RouteProcessor to addresses\n /// @notice Quantity for sending is determined by share in 1/65535\n /// @notice During routing we can't predict in advance the actual value of internal swaps because of slippage,\n /// @notice so we have to work with shares - not fixed amounts\n /// @param stream [Token, ArrayLength, ...[To, ShareAmount][]]. Token to distribute. An array of destinations and token share amounts\n function distributeERC20Shares(uint256 stream) private {\n address token = stream.readAddress();\n uint8 num = stream.readUint8();\n uint256 amountTotal = IERC20(token).balanceOf(address(this))\n - 1; // slot undrain protection\n\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n address to = stream.readAddress();\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / 65535;\n amountTotal -= amount;\n IERC20(token).safeTransfer(to, amount);\n }\n }\n }\n\n /// @notice Distributes BentoBox tokens from RouteProcessor to addresses\n /// @notice Quantity for sending is determined by portions in 1/65535.\n /// @notice During routing we can't predict in advance the actual value of internal swaps because of slippage,\n /// @notice so we have to work with portions - not fixed amounts\n /// @param stream [Token, ArrayLength, ...[To, ShareAmount][]]. Token to distribute. An array of destinations and token share amounts\n function distributeBentoPortions(uint256 stream) private {\n address token = stream.readAddress();\n uint8 num = stream.readUint8();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this))\n - 1; // slot undrain protection\n\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n address to = stream.readAddress();\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / 65535;\n amountTotal -= amount;\n bentoBox.transfer(token, address(this), to, amount);\n }\n }\n }\n\n /// @notice Unwraps the Native Token\n /// @param receiver Destination of the unwrapped token\n /// @param stream [Token]. Token to unwrap native\n function unwrapNative(address receiver, uint256 stream) private {\n address token = stream.readAddress();\n IWETH(token).withdraw( IERC20(token).balanceOf(address(this))\n - 1); // slot undrain protection\n payable(receiver).transfer(address(this).balance);\n }\n}\n" + }, + "contracts/RouteProcessor3_1.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport './InputStream.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\n/// version 3.1\ncontract RouteProcessor3_1 is Ownable {\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint amountIn, \n uint amountOutMin,\n uint amountOut\n );\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = 1;\n uint8 private paused = 1;\n modifier lock() {\n require(unlocked == 1, 'RouteProcessor is locked');\n require(paused == 1, 'RouteProcessor is paused');\n unlocked = 2;\n _;\n unlocked = 1;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender] == true, \"RP: caller is not the owner or a priviledged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = 2;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = 1;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n (bool success, bytes memory returnBytes) = transferValueTo.call{value: amountValueTransfer}('');\n require(success, string(abi.encodePacked(returnBytes)));\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn == NATIVE_ADDRESS ? address(this).balance : IERC20(tokenIn).balanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut == NATIVE_ADDRESS ? address(to).balance : IERC20(tokenOut).balanceOf(to);\n\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) processMyERC20(stream);\n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) processNative(stream);\n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n }\n\n uint256 balanceInFinal = tokenIn == NATIVE_ADDRESS ? address(this).balance : IERC20(tokenIn).balanceOf(msg.sender);\n require(balanceInFinal + amountIn >= balanceInInitial, 'RouteProcessor: Minimal imput balance violation');\n\n uint256 balanceOutFinal = tokenOut == NATIVE_ADDRESS ? address(to).balance : IERC20(tokenOut).balanceOf(to);\n require(balanceOutFinal >= balanceOutInitial + amountOutMin, 'RouteProcessor: Minimal ouput balance violation');\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, amountIn, amountOutMin, amountOut);\n }\n\n function applyPermit(address tokenIn, uint256 stream) private {\n //address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s)\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed process program\n function processNative(uint256 stream) private {\n uint256 amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n function processMyERC20(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed process program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / 65535;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, address(this), token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint8 num = stream.readUint8();\n\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / 65535;\n amountTotal -= amount;\n swap(stream, address(this), token, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed process program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from != address(this)) IERC20(tokenIn).safeTransferFrom(from, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n payable(to).transfer(address(this).balance);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (amountIn != 0) {\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else IERC20(tokenIn).safeTransferFrom(from, address(bentoBox), amountIn);\n } else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (amountIn > 0) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n\n if (amountIn != 0) {\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else IERC20(tokenIn).safeTransferFrom(from, pool, amountIn);\n }\n // without 'else' in order to support tax tokens\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * 997;\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (amountIn != 0) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from != address(this)) {\n require(from == msg.sender, 'swapUniV3: unexpected from address');\n IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n }\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n\n // Normally, RouteProcessor shouldn't have any liquidity on board\n // If some liquidity exists, it is sweept by the next user that makes swap through these tokens\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n}\n" + }, + "contracts/RouteProcessor3_2.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport './InputStream.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\n/// version 3.2\ncontract RouteProcessor3_2 is Ownable {\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint amountIn, \n uint amountOutMin,\n uint amountOut\n );\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = 1;\n uint8 private paused = 1;\n modifier lock() {\n require(unlocked == 1, 'RouteProcessor is locked');\n require(paused == 1, 'RouteProcessor is paused');\n unlocked = 2;\n _;\n unlocked = 1;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender] == true, \"RP: caller is not the owner or a priviledged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = 2;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = 1;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n (bool success, bytes memory returnBytes) = transferValueTo.call{value: amountValueTransfer}('');\n require(success, string(abi.encodePacked(returnBytes)));\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn == NATIVE_ADDRESS ? address(this).balance : IERC20(tokenIn).balanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut == NATIVE_ADDRESS ? address(to).balance : IERC20(tokenOut).balanceOf(to);\n\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) processMyERC20(stream);\n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) processNative(stream);\n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n }\n\n uint256 balanceInFinal = tokenIn == NATIVE_ADDRESS ? address(this).balance : IERC20(tokenIn).balanceOf(msg.sender);\n require(balanceInFinal + amountIn >= balanceInInitial, 'RouteProcessor: Minimal imput balance violation');\n\n uint256 balanceOutFinal = tokenOut == NATIVE_ADDRESS ? address(to).balance : IERC20(tokenOut).balanceOf(to);\n require(balanceOutFinal >= balanceOutInitial + amountOutMin, 'RouteProcessor: Minimal ouput balance violation');\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, amountIn, amountOutMin, amountOut);\n }\n\n function applyPermit(address tokenIn, uint256 stream) private {\n //address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s)\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed process program\n function processNative(uint256 stream) private {\n uint256 amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n function processMyERC20(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed process program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / 65535;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, address(this), token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint8 num = stream.readUint8();\n\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / 65535;\n amountTotal -= amount;\n swap(stream, address(this), token, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed process program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from != address(this)) IERC20(tokenIn).safeTransferFrom(from, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n payable(to).transfer(address(this).balance);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (amountIn != 0) {\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else IERC20(tokenIn).safeTransferFrom(from, address(bentoBox), amountIn);\n } else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (amountIn > 0) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (amountIn != 0) {\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else IERC20(tokenIn).safeTransferFrom(from, pool, amountIn);\n }\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * 997;\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (amountIn != 0) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from != address(this)) {\n require(from == msg.sender, 'swapUniV3: unexpected from address');\n IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n }\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n\n // Normally, RouteProcessor shouldn't have any liquidity on board\n // If some liquidity exists, it is sweept by the next user that makes swap through these tokens\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n}\n" + }, + "contracts/RouteProcessor3.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport './InputStream.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\n/// version 2.1\ncontract RouteProcessor3 is Ownable {\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint amountIn, \n uint amountOutMin,\n uint amountOut\n );\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = 1;\n uint8 private paused = 1;\n modifier lock() {\n require(unlocked == 1, 'RouteProcessor is locked');\n require(paused == 1, 'RouteProcessor is paused');\n unlocked = 2;\n _;\n unlocked = 1;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender] == true, \"RP: caller is not the owner or a priviledged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = 2;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = 1;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n (bool success, bytes memory returnBytes) = transferValueTo.call{value: amountValueTransfer}('');\n require(success, string(abi.encodePacked(returnBytes)));\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn == NATIVE_ADDRESS ? address(this).balance : IERC20(tokenIn).balanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut == NATIVE_ADDRESS ? address(to).balance : IERC20(tokenOut).balanceOf(to);\n\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) processMyERC20(stream);\n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) processNative(stream);\n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n }\n\n uint256 balanceInFinal = tokenIn == NATIVE_ADDRESS ? address(this).balance : IERC20(tokenIn).balanceOf(msg.sender);\n require(balanceInFinal + amountIn >= balanceInInitial, 'RouteProcessor: Minimal imput balance violation');\n\n uint256 balanceOutFinal = tokenOut == NATIVE_ADDRESS ? address(to).balance : IERC20(tokenOut).balanceOf(to);\n require(balanceOutFinal >= balanceOutInitial + amountOutMin, 'RouteProcessor: Minimal ouput balance violation');\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, amountIn, amountOutMin, amountOut);\n }\n\n function applyPermit(address tokenIn, uint256 stream) private {\n //address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s)\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed process program\n function processNative(uint256 stream) private {\n uint256 amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n function processMyERC20(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed process program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / 65535;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, address(this), token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint8 num = stream.readUint8();\n\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / 65535;\n amountTotal -= amount;\n swap(stream, address(this), token, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed process program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from != address(this)) IERC20(tokenIn).safeTransferFrom(from, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n payable(to).transfer(address(this).balance);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (amountIn != 0) {\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else IERC20(tokenIn).safeTransferFrom(from, address(bentoBox), amountIn);\n } else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (amountIn > 0) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n\n if (amountIn != 0) {\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else IERC20(tokenIn).safeTransferFrom(from, pool, amountIn);\n } else amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * 997;\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (amountIn != 0) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from != address(this)) {\n require(from == msg.sender, 'swapUniV3: unexpected from address');\n IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n }\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n\n // Normally, RouteProcessor shouldn't have any liquidity on board\n // If some liquidity exists, it is sweept by the next user that makes swap through these tokens\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n}\n" + }, + "contracts/RouteProcessor4.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Approve.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor4 is Ownable {\n using SafeERC20 for IERC20;\n using Approve for IERC20;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n (bool success, bytes memory returnBytes) = transferValueTo.call{value: amountValueTransfer}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn == NATIVE_ADDRESS ? 0 : IERC20(tokenIn).balanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut == NATIVE_ADDRESS ? address(to).balance : IERC20(tokenOut).balanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn == NATIVE_ADDRESS ? 0 : IERC20(tokenIn).balanceOf(msg.sender);\n require(balanceInFinal + amountIn >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut == NATIVE_ADDRESS ? address(to).balance : IERC20(tokenOut).balanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n (bool success,)= payable(to).call{value: amountIn}(\"\");\n require(success, \"RouteProcessor.wrapNative: Native token transfer failed\");\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = IERC20(tokenOut).balanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = IERC20(tokenOut).balanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) { \n if(tokenOut == NATIVE_ADDRESS) {\n (bool success,)= payable(to).call{value: amountOut}(\"\");\n require(success, \"RouteProcessor.swapCurve: Native token transfer failed\");\n } else {\n IERC20(tokenOut).safeTransfer(to, amountOut);\n }\n }\n }\n}\n" + }, + "contracts/RouteProcessor5.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" + }, + "contracts/Utils.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "interfaces/IBentoBoxMinimal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" + }, + "interfaces/ICurve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" + }, + "interfaces/IPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" + }, + "interfaces/ITridentCLPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/skale-europa/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json b/protocols/route-processor/deployments/skale-europa/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json deleted file mode 100644 index 01826e7b93..0000000000 --- a/protocols/route-processor/deployments/skale-europa/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json +++ /dev/null @@ -1,80 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "@openzeppelin/contracts/access/Ownable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" - }, - "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" - }, - "@openzeppelin/contracts/token/ERC20/IERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" - }, - "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" - }, - "@openzeppelin/contracts/utils/Address.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" - }, - "@openzeppelin/contracts/utils/Context.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" - }, - "contracts/InputStream.sol": { - "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" - }, - "contracts/RouteProcessor5.sol": { - "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" - }, - "contracts/Utils.sol": { - "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" - }, - "interfaces/IBentoBoxMinimal.sol": { - "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" - }, - "interfaces/ICurve.sol": { - "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" - }, - "interfaces/IPool.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" - }, - "interfaces/ITridentCLPool.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" - }, - "interfaces/IUniswapV2Pair.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" - }, - "interfaces/IUniswapV3Pool.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" - }, - "interfaces/IWETH.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" - } - }, - "settings": { - "optimizer": { - "enabled": true, - "runs": 10000000 - }, - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "devdoc", - "userdoc", - "storageLayout", - "evm.gasEstimates" - ], - "": [ - "ast" - ] - } - }, - "metadata": { - "useLiteralContent": true - } - } -} \ No newline at end of file From e2eb6fcbc24784b6e7d073c6356410c2020144a5 Mon Sep 17 00:00:00 2001 From: 0xMasayoshi <0xMasayoshi@protonmail.com> Date: Thu, 1 Aug 2024 11:49:11 +0700 Subject: [PATCH 012/125] chore: update boba RP5 deployment files --- .../deployments/boba/RouteProcessor5.json | 36 +++---- .../9252879aaeb02fabe759ce8768addec4.json | 98 +++++++++++++++++++ .../e556d43a3caf4f1fb4f12d632d103b28.json | 80 --------------- 3 files changed, 116 insertions(+), 98 deletions(-) create mode 100644 protocols/route-processor/deployments/boba/solcInputs/9252879aaeb02fabe759ce8768addec4.json delete mode 100644 protocols/route-processor/deployments/boba/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json diff --git a/protocols/route-processor/deployments/boba/RouteProcessor5.json b/protocols/route-processor/deployments/boba/RouteProcessor5.json index bf45fed157..88b32fd3aa 100644 --- a/protocols/route-processor/deployments/boba/RouteProcessor5.json +++ b/protocols/route-processor/deployments/boba/RouteProcessor5.json @@ -1,5 +1,5 @@ { - "address": "0x1f2FCf1d036b375b384012e61D3AA33F8C256bbE", + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", "abi": [ { "inputs": [ @@ -473,33 +473,33 @@ "type": "receive" } ], - "transactionHash": "0x99180d89f8a75b05f527e6ebcb5ae9bd9e40621ee7a3d2fca2815ae92f731bcb", + "transactionHash": "0x579667efd922fd193fd485625ba2284bef30d5ba3b5a1bde97db3af5ffc864fd", "receipt": { "to": null, - "from": "0x69aea8e393e14945EC22f33B422e7269967e6327", - "contractAddress": "0x1f2FCf1d036b375b384012e61D3AA33F8C256bbE", + "from": "0x282607716D9B4fDD0B094d5864fac56313f5e665", + "contractAddress": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", "transactionIndex": 1, "gasUsed": "3489875", - "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000200000000000000000000000000020000000000000000000800000000000000000040000000000000400000000000000000000000000000000000000000002100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000080000000020000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x60007d44af8c6cf27f889cd606d783582cb60607049d2bba1eea4cc20e86b7fe", - "transactionHash": "0x99180d89f8a75b05f527e6ebcb5ae9bd9e40621ee7a3d2fca2815ae92f731bcb", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000020000000000000000000000000000000000000001000000000000000000000000000000000000000000040000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000000000000000000000000000", + "blockHash": "0xf85d78368456881cbde9489fa7e6e44167cf22cde76e6a884ff6d1c8be2fc680", + "transactionHash": "0x579667efd922fd193fd485625ba2284bef30d5ba3b5a1bde97db3af5ffc864fd", "logs": [ { "transactionIndex": 1, - "blockNumber": 5625741, - "transactionHash": "0x99180d89f8a75b05f527e6ebcb5ae9bd9e40621ee7a3d2fca2815ae92f731bcb", - "address": "0x1f2FCf1d036b375b384012e61D3AA33F8C256bbE", + "blockNumber": 5741316, + "transactionHash": "0x579667efd922fd193fd485625ba2284bef30d5ba3b5a1bde97db3af5ffc864fd", + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", "topics": [ "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x00000000000000000000000069aea8e393e14945ec22f33b422e7269967e6327" + "0x000000000000000000000000282607716d9b4fdd0b094d5864fac56313f5e665" ], "data": "0x", "logIndex": 0, - "blockHash": "0x60007d44af8c6cf27f889cd606d783582cb60607049d2bba1eea4cc20e86b7fe" + "blockHash": "0xf85d78368456881cbde9489fa7e6e44167cf22cde76e6a884ff6d1c8be2fc680" } ], - "blockNumber": 5625741, + "blockNumber": 5741316, "cumulativeGasUsed": "3533690", "status": 1, "byzantium": true @@ -509,7 +509,7 @@ [] ], "numDeployments": 1, - "solcInputHash": "e556d43a3caf4f1fb4f12d632d103b28", + "solcInputHash": "9252879aaeb02fabe759ce8768addec4", "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bentoBox\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"priviledgedUserList\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"MinimalOutputBalanceViolation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"Route\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"algebraSwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"pancakeV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"priviledgedUsers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"priviledge\",\"type\":\"bool\"}],\"name\":\"setPriviledge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"transferValueAndprocessRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"Ilya Lyalin\",\"kind\":\"dev\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IAlgebraPoolActions#swap call\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the PancakeV3Pool#swap call\"}},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"route\":\"Route to process\",\"to\":\"Where to transfer output tokens\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IUniswapV3PoolActions#swap call\"}}},\"title\":\"A route processor for the Sushi Aggregator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\"},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Processes the route generated off-chain. Has a lock\"},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value of input tokens to and then processes the route\"},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"processes the route and sends amount of output token to \"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value to and then processes the route\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RouteProcessor5.sol\":\"RouteProcessor5\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\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 Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.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 function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\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\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\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 * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\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\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/InputStream.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\n/** @notice Simple read stream */\\nlibrary InputStream {\\n\\n /** @notice Creates stream from data\\n * @param data data\\n */\\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\\n assembly {\\n stream := mload(0x40)\\n mstore(0x40, add(stream, 64))\\n mstore(stream, data)\\n let length := mload(data)\\n mstore(add(stream, 32), add(data, length))\\n }\\n }\\n\\n /** @notice Checks if stream is not empty\\n * @param stream stream\\n */\\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\\n uint256 pos;\\n uint256 finish;\\n assembly {\\n pos := mload(stream)\\n finish := mload(add(stream, 32))\\n }\\n return pos < finish;\\n }\\n\\n /** @notice Reads uint8 from the stream\\n * @param stream stream\\n */\\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 1)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint16 from the stream\\n * @param stream stream\\n */\\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 2)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint24 from the stream\\n * @param stream stream\\n */\\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 3)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint32 from the stream\\n * @param stream stream\\n */\\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 4)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint256 from the stream\\n * @param stream stream\\n */\\n function readUint(uint256 stream) internal pure returns (uint256 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes32 from the stream\\n * @param stream stream\\n */\\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads address from the stream\\n * @param stream stream\\n */\\n function readAddress(uint256 stream) internal pure returns (address res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 20)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes from the stream\\n * @param stream stream\\n */\\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\\n assembly {\\n let pos := mload(stream)\\n res := add(pos, 32)\\n let length := mload(res)\\n mstore(stream, add(res, length))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x24e24bd0e49cbddacbf3b26bcd4bdffac63d11f3259bc05bc93c0835e8ff5300\",\"license\":\"UNLICENSED\"},\"contracts/RouteProcessor5.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '../interfaces/IUniswapV2Pair.sol';\\nimport '../interfaces/IUniswapV3Pool.sol';\\nimport '../interfaces/ITridentCLPool.sol';\\nimport '../interfaces/IBentoBoxMinimal.sol';\\nimport '../interfaces/IPool.sol';\\nimport '../interfaces/IWETH.sol';\\nimport '../interfaces/ICurve.sol';\\nimport './InputStream.sol';\\nimport './Utils.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\\n\\nuint8 constant LOCKED = 2;\\nuint8 constant NOT_LOCKED = 1;\\nuint8 constant PAUSED = 2;\\nuint8 constant NOT_PAUSED = 1;\\n\\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\nuint160 constant MIN_SQRT_RATIO = 4295128739;\\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n/// @title A route processor for the Sushi Aggregator\\n/// @author Ilya Lyalin\\ncontract RouteProcessor5 is Ownable {\\n using SafeERC20 for IERC20;\\n using Utils for IERC20;\\n using Utils for address;\\n using SafeERC20 for IERC20Permit;\\n using InputStream for uint256;\\n\\n event Route(\\n address indexed from, \\n address to, \\n address indexed tokenIn, \\n address indexed tokenOut, \\n uint256 amountIn, \\n uint256 amountOutMin,\\n uint256 amountOut\\n );\\n\\n error MinimalOutputBalanceViolation(uint256 amountOut);\\n\\n IBentoBoxMinimal public immutable bentoBox;\\n mapping (address => bool) public priviledgedUsers;\\n address private lastCalledPool;\\n\\n uint8 private unlocked = NOT_LOCKED;\\n uint8 private paused = NOT_PAUSED;\\n modifier lock() {\\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\\n unlocked = LOCKED;\\n _;\\n unlocked = NOT_LOCKED;\\n }\\n\\n modifier onlyOwnerOrPriviledgedUser() {\\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \\\"RP: caller is not the owner or a privileged user\\\");\\n _;\\n }\\n\\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\\n bentoBox = IBentoBoxMinimal(_bentoBox);\\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n\\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\\n priviledgedUsers[priviledgedUserList[i]] = true;\\n }\\n }\\n\\n function setPriviledge(address user, bool priviledge) external onlyOwner {\\n priviledgedUsers[user] = priviledge;\\n }\\n\\n function pause() external onlyOwnerOrPriviledgedUser {\\n paused = PAUSED;\\n }\\n\\n function resume() external onlyOwnerOrPriviledgedUser {\\n paused = NOT_PAUSED;\\n }\\n\\n /// @notice For native unwrapping\\n receive() external payable {}\\n\\n /// @notice Processes the route generated off-chain. Has a lock\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @param to Where to transfer output tokens\\n /// @param route Route to process\\n /// @return amountOut Actual amount of the output token\\n function processRoute(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function transferValueAndprocessRoute(\\n address transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n transferValueTo.transferNative(amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value of input tokens to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueInput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n \\n /// @notice processes the route and sends amount of output token to \\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueOutput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\\n }\\n\\n /// @notice Processes the route generated off-chain\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteInternal(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) private returns (uint256 amountOut) {\\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\\n\\n uint256 realAmountIn = amountIn;\\n {\\n uint256 step = 0;\\n uint256 stream = InputStream.createStream(route);\\n while (stream.isNotEmpty()) {\\n uint8 commandCode = stream.readUint8();\\n if (commandCode == 1) {\\n uint256 usedAmount = processMyERC20(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 2) processUserERC20(stream, amountIn);\\n else if (commandCode == 3) {\\n uint256 usedAmount = processNative(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 4) processOnePool(stream);\\n else if (commandCode == 5) processInsideBento(stream);\\n else if (commandCode == 6) applyPermit(tokenIn, stream);\\n else revert('RouteProcessor: Unknown command code');\\n ++step;\\n }\\n }\\n\\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\\n if (tokenIn != Utils.NATIVE_ADDRESS)\\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\\n \\n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\\n\\n amountOut = balanceOutFinal - balanceOutInitial;\\n\\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\\n }\\n\\n /// @notice Applies ERC-2612 permit\\n /// @param tokenIn permitted token\\n /// @param stream Streamed program\\n function applyPermit(address tokenIn, uint256 stream) private {\\n uint256 value = stream.readUint();\\n uint256 deadline = stream.readUint();\\n uint8 v = stream.readUint8();\\n bytes32 r = stream.readBytes32();\\n bytes32 s = stream.readBytes32();\\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\\n }\\n }\\n\\n /// @notice Processes native coin: call swap for all pools that swap from native coin\\n /// @param stream Streamed program\\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\\n amountTotal = address(this).balance;\\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token from this contract balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\\n address token = stream.readAddress();\\n amountTotal = IERC20(token).balanceOf(address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n \\n /// @notice Processes ERC20 token from msg.sender balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n /// @param amountTotal Amount of tokens to take from msg.sender\\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\\n address token = stream.readAddress();\\n distributeAndSwap(stream, msg.sender, token, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token for cases when the token has only one output pool\\n /// @notice In this case liquidity is already at pool balance. This is an optimization\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processOnePool(uint256 stream) private {\\n address token = stream.readAddress();\\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\\n }\\n\\n /// @notice Processes Bento tokens \\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processInsideBento(uint256 stream) private {\\n address token = stream.readAddress();\\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n\\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountTotal Total amount of tokenIn for swaps \\n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\\n uint8 num = stream.readUint8();\\n unchecked {\\n for (uint256 i = 0; i < num; ++i) {\\n uint16 share = stream.readUint16();\\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\\n amountTotal -= amount;\\n swap(stream, from, tokenIn, amount);\\n }\\n }\\n }\\n\\n /// @notice Makes swap\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 poolType = stream.readUint8();\\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\\n else revert('RouteProcessor: Unknown pool type');\\n }\\n\\n /// @notice Wraps/unwraps native token\\n /// @param stream [direction & fake, recipient, wrapToken?]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 directionAndFake = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (directionAndFake & 1 == 1) { // wrap native\\n address wrapToken = stream.readAddress();\\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\\n } else { // unwrap native\\n if (directionAndFake & 2 == 0) {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IWETH(tokenIn).withdraw(amountIn);\\n }\\n to.transferNative(amountIn);\\n }\\n }\\n\\n /// @notice Bridge/unbridge tokens to/from Bento\\n /// @param stream [direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (direction > 0) { // outside to Bento\\n // deposit to arbitrary recipient is possible only from address(bentoBox)\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\\n else {\\n // tokens already are at address(bentoBox)\\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\\n bentoBox.strategyData(tokenIn).balance -\\n bentoBox.totals(tokenIn).elastic;\\n }\\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\\n } else { // Bento to outside\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\\n }\\n }\\n\\n /// @notice UniswapV2 pool swap\\n /// @param stream [pool, direction, recipient, fee]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\\n\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\\n\\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\\n\\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\\n }\\n\\n /// @notice Trident pool swap\\n /// @param stream [pool, swapData]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bytes memory swapData = stream.readBytes();\\n\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, pool, amountIn);\\n }\\n \\n IPool(pool).swap(swapData);\\n }\\n\\n /// @notice UniswapV3 pool swap\\n /// @param stream [pool, direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bool zeroForOne = stream.readUint8() > 0;\\n address recipient = stream.readAddress();\\n\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\\n\\n lastCalledPool = pool;\\n IUniswapV3Pool(pool).swap(\\n recipient,\\n zeroForOne,\\n int256(amountIn),\\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\\n abi.encode(tokenIn)\\n );\\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) public {\\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\\n \\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n (address tokenIn) = abi.decode(data, (address));\\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\\n function algebraSwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\\n function pancakeV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 poolType = stream.readUint8();\\n int128 fromIndex = int8(stream.readUint8());\\n int128 toIndex = int8(stream.readUint8());\\n address to = stream.readAddress();\\n address tokenOut = stream.readAddress();\\n\\n uint256 amountOut;\\n if (tokenIn == Utils.NATIVE_ADDRESS) {\\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\\n } else {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IERC20(tokenIn).approveSafe(pool, amountIn);\\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n else {\\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\\n amountOut = balanceAfter - balanceBefore;\\n }\\n }\\n\\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\\n }\\n}\\n\",\"keccak256\":\"0xcd53a7f473f1847d44c42777a194203cbff02b8c761cb2935402401f57c918a2\",\"license\":\"UNLICENSED\"},\"contracts/Utils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\n\\nlibrary Utils {\\n using SafeERC20 for IERC20;\\n\\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n /**\\n * @dev returns user's balance of token (or native)\\n */\\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\\n if (token == NATIVE_ADDRESS) return address(user).balance;\\n else return IERC20(token).balanceOf(user);\\n }\\n\\n /**\\n * @dev transfers native with correct revert bubble up\\n */\\n function transferNative(address to, uint256 amount) internal {\\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\\n if (!success) {\\n assembly {\\n revert(add(32, returnBytes), mload(returnBytes))\\n }\\n }\\n }\\n\\n /**\\n * @dev transfers ERC20 or native\\n */\\n function transferAny(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\\n else IERC20(token).safeTransfer(to, amount);\\n }\\n\\n /**\\n * @dev transfers from ERC20 or transfers native\\n */\\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n (bool success, bytes memory data) = address(token).call(\\n abi.encodeWithSelector(token.approve.selector, spender, amount)\\n );\\n return success && (data.length == 0 || abi.decode(data, (bool)));\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \\n * current allowance are not zero simultaniously (USDT for example). \\n * In second case it tries to set allowance to 0, and then back to amount.\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n return approveStable(token, spender, amount) \\n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\\n }\\n}\\n\",\"keccak256\":\"0x8c8439edc00b403abd3f34be75a06b1fe71152644ae9f19488af596bbc534ffe\",\"license\":\"UNLICENSED\"},\"interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\nstruct StrategyData {\\n uint64 strategyStartDate;\\n uint64 targetPercentage;\\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n function strategyData(address token) external view returns (StrategyData memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0x0c12eba7a5b9d22d37ab8883fe22d6a312a90682809dbd11c43f8e6ceaff73bf\",\"license\":\"UNLICENSED\"},\"interfaces/ICurve.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\ninterface ICurve {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\\n}\\n\\ninterface ICurveLegacy {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\\n}\\n\\n\",\"keccak256\":\"0x3d4940b3583e06dde20f12e92d2f6ac573b3f64bdaa1e8f480656a3763852518\",\"license\":\"UNLICENSED\"},\"interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/ITridentCLPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface ITridentCLPool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bool unwrapBento,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x572376b80c86a94692b0e27e6e63790b763295e32ba1f956c1d331fc1296de8d\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IUniswapV2Pair.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Pair {\\n event Approval(address indexed owner, address indexed spender, uint value);\\n event Transfer(address indexed from, address indexed to, uint value);\\n\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function allowance(address owner, address spender) external view returns (uint);\\n\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address to, uint value) external returns (bool);\\n function transferFrom(address from, address to, uint value) external returns (bool);\\n\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n function nonces(address owner) external view returns (uint);\\n\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n event Mint(address indexed sender, uint amount0, uint amount1);\\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\\n event Swap(\\n address indexed sender,\\n uint amount0In,\\n uint amount1In,\\n uint amount0Out,\\n uint amount1Out,\\n address indexed to\\n );\\n event Sync(uint112 reserve0, uint112 reserve1);\\n\\n function MINIMUM_LIQUIDITY() external pure returns (uint);\\n function factory() external view returns (address);\\n function token0() external view returns (address);\\n function token1() external view returns (address);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\\n function price0CumulativeLast() external view returns (uint);\\n function price1CumulativeLast() external view returns (uint);\\n function kLast() external view returns (uint);\\n\\n function mint(address to) external returns (uint liquidity);\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function skim(address to) external;\\n function sync() external;\\n\\n function initialize(address, address) external;\\n}\",\"keccak256\":\"0x08f9a63b34855eec941be8d36a04424f1a1725a2c030373fcef3afeb480ca385\",\"license\":\"GPL-3.0\"},\"interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IUniswapV3Pool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x2a4d7c6120e613f0e95d4dc8c650efb9b59e3c25c64e3e5c0a379281500f0a79\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IWETH.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0xae8529ae159f784b90fdcd0629bd03bf7b68accc81edccac53357ad08406a378\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}", "bytecode": "0x60a06040526002805461ffff60a01b191661010160a01b1790553480156200002657600080fd5b50604051620040a3380380620040a383398101604081905262000049916200016e565b6200005433620000eb565b6001600160a01b038216608052600280546001600160a01b031916600117905560005b8151811015620000e25760018060008484815181106200009b576200009b62000257565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000d9816200026d565b91505062000077565b50505062000297565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200015357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200018257600080fd5b6200018d836200013b565b602084810151919350906001600160401b0380821115620001ad57600080fd5b818601915086601f830112620001c257600080fd5b815181811115620001d757620001d762000158565b8060051b604051601f19603f83011681018181108582111715620001ff57620001ff62000158565b6040529182528482019250838101850191898311156200021e57600080fd5b938501935b82851015620002475762000237856200013b565b8452938501939285019262000223565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200029057634e487b7160e01b600052601160045260246000fd5b5060010190565b608051613da3620003006000396000818161018d01528181611798015281816127380152818161279d01528181612807015281816128cc0152818161297901528181612a5d01528181612b6401528181612c1001528181612cdf0152612df10152613da36000f3fe6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", "deployedBytecode": "0x6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", @@ -644,7 +644,7 @@ "type": "t_address" }, { - "astId": 1060, + "astId": 8573, "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", "label": "priviledgedUsers", "offset": 0, @@ -652,7 +652,7 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1062, + "astId": 8575, "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", "label": "lastCalledPool", "offset": 0, @@ -660,7 +660,7 @@ "type": "t_address" }, { - "astId": 1065, + "astId": 8578, "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", "label": "unlocked", "offset": 20, @@ -668,7 +668,7 @@ "type": "t_uint8" }, { - "astId": 1068, + "astId": 8581, "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", "label": "paused", "offset": 21, diff --git a/protocols/route-processor/deployments/boba/solcInputs/9252879aaeb02fabe759ce8768addec4.json b/protocols/route-processor/deployments/boba/solcInputs/9252879aaeb02fabe759ce8768addec4.json new file mode 100644 index 0000000000..c6762a8dc1 --- /dev/null +++ b/protocols/route-processor/deployments/boba/solcInputs/9252879aaeb02fabe759ce8768addec4.json @@ -0,0 +1,98 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" + }, + "contracts/Approve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\n\nlibrary Approve {\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "contracts/InputStream.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" + }, + "contracts/RouteProcessor.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport './InputStream.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\naddress constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Okavango\ncontract RouteProcessor {\n using SafeERC20 for IERC20;\n using InputStream for uint256;\n\n IBentoBoxMinimal public immutable bentoBox;\n\n uint private unlocked = 1;\n modifier lock() {\n require(unlocked == 1, 'RouteProcessor is locked');\n unlocked = 2;\n _;\n unlocked = 1;\n }\n\n constructor(address _bentoBox) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n (bool success, bytes memory returnBytes) = transferValueTo.call{value: amountValueTransfer}('');\n require(success, string(abi.encodePacked(returnBytes)));\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 amountInAcc = 0;\n uint256 balanceInitial = tokenOut == NATIVE_ADDRESS ? \n address(to).balance : IERC20(tokenOut).balanceOf(to);\n\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode < 20) {\n if (commandCode == 10)\n swapUniswapPool(stream); // Sushi/Uniswap pool swap\n else if (commandCode == 4)\n distributeERC20Shares(stream); // distribute ERC20 tokens from this router to pools\n else if (commandCode == 3)\n amountInAcc += distributeERC20Amounts(stream, tokenIn); // initial distribution\n else if (commandCode == 5)\n amountInAcc += wrapAndDistributeERC20Amounts(stream); // wrap natives and initial distribution \n else if (commandCode == 6) \n unwrapNative(to, stream);\n else if (commandCode == 7)\n amountInAcc += distributeERC20AmountsFromRP(stream, tokenIn); // initial distribution\n else revert('Unknown command code');\n } else if (commandCode < 24) {\n if (commandCode == 20) bentoDepositAmountFromBento(stream, tokenIn);\n else if (commandCode == 21) swapTrident(stream);\n else if (commandCode == 23) bentoWithdrawShareFromRP(stream, tokenIn);\n else revert('Unknown command code');\n } else {\n if (commandCode == 24) amountInAcc += distributeBentoShares(stream, tokenIn);\n else if (commandCode == 25) distributeBentoPortions(stream);\n else if (commandCode == 26) bentoDepositAllFromBento(stream);\n else if (commandCode == 27) bentoWithdrawAllFromRP(stream);\n else revert('Unknown command code');\n }\n }\n\n require(amountInAcc == amountIn, 'Wrong amountIn value');\n uint256 balanceFinal = tokenOut == NATIVE_ADDRESS ? \n address(to).balance : IERC20(tokenOut).balanceOf(to);\n require(balanceFinal >= balanceInitial + amountOutMin, 'Minimal ouput balance violation');\n\n amountOut = balanceFinal - balanceInitial;\n }\n\n /// @notice Transfers input tokens sent to BentoBox to a pool\n /// @notice Expected to be called for initial liquidity transfer from user to BentoBox, so we know exact amounts\n /// @param stream [Pool, Amount]. Pool into which an amount of tokens will be transferred\n /// @param token Address of the token to transfer\n function bentoDepositAmountFromBento(uint256 stream, address token) private {\n address to = stream.readAddress();\n uint256 amount = stream.readUint();\n bentoBox.deposit(token, address(bentoBox), to, amount, 0);\n }\n\n /// @notice Transfers all available input tokens from BentoBox to a pool\n /// @param stream [Pool, Token]. Pool into which all tokens will be transferred \n function bentoDepositAllFromBento(uint256 stream) private {\n address to = stream.readAddress();\n address token = stream.readAddress();\n\n uint256 amount = IERC20(token).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(token).balance -\n bentoBox.totals(token).elastic;\n bentoBox.deposit(token, address(bentoBox), to, amount, 0);\n }\n\n /// @notice Withdraws BentoBox tokens from BentoBox to an address\n /// @param stream [To, Amount]. Destination where an amount of token will be transferred\n /// @param token Token to transfer\n function bentoWithdrawShareFromRP(uint256 stream, address token) private {\n address to = stream.readAddress();\n uint256 amount = stream.readUint();\n bentoBox.withdraw(token, address(this), to, amount, 0);\n }\n\n /// @notice Withdraws all available BentoBox tokens from BentoBox to an address\n /// @param stream [Token, To]. Token which will be transferred to a destination\n function bentoWithdrawAllFromRP(uint256 stream) private {\n address token = stream.readAddress();\n address to = stream.readAddress();\n uint256 amount = bentoBox.balanceOf(token, address(this));\n bentoBox.withdraw(token, address(this), to, 0, amount);\n }\n\n /// @notice Performs a Trident pool swap\n /// @param stream [Pool, SwapData]. Pool against a swap defined by SwapData will be executed\n function swapTrident(uint256 stream) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n IPool(pool).swap(swapData);\n }\n\n /// @notice Performs a Sushi/UniswapV2 pool swap\n /// @param stream [Pool, TokenIn, Direction, To]\n /// @return amountOut Amount of the output token\n function swapUniswapPool(uint256 stream) private returns (uint256 amountOut) {\n address pool = stream.readAddress();\n address tokenIn = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n\n uint256 amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn;\n uint256 amountInWithFee = amountIn * 997;\n amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Distributes input ERC20 tokens from msg.sender to addresses. Tokens should be approved\n /// @notice Expected to be called for initial liquidity transfer from the user to pools, so we know exact amounts\n /// @param stream [ArrayLength, ...[To, Amount][]]. An array of destinations and token amounts\n /// @param token Token to distribute\n /// @return amountTotal Total amount distributed\n function distributeERC20Amounts(uint256 stream, address token) private returns (uint256 amountTotal) {\n uint8 num = stream.readUint8();\n amountTotal = 0;\n for (uint256 i = 0; i < num; ++i) {\n address to = stream.readAddress();\n uint256 amount = stream.readUint();\n amountTotal += amount;\n IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n }\n\n /// @notice Distributes input ERC20 tokens from this contract to addresses. Tokens should be approved\n /// @notice Expected to be called for initial liquidity transfer from the user to pools, so we know exact amounts\n /// @param stream [ArrayLength, ...[To, Amount][]]. An array of destinations and token amounts\n /// @param token Token to distribute\n /// @return amountTotal Total amount distributed\n function distributeERC20AmountsFromRP(uint256 stream, address token) private returns (uint256 amountTotal) {\n uint8 num = stream.readUint8();\n amountTotal = 0;\n for (uint256 i = 0; i < num; ++i) {\n address to = stream.readAddress();\n uint256 amount = stream.readUint();\n amountTotal += amount;\n IERC20(token).safeTransfer(to, amount);\n }\n }\n\n /// @notice Wraps all native inputs and distributes wrapped ERC20 tokens from RouteProcessor to addresses\n /// @notice Expected to be called for initial liquidity transfer from the user to pools, so we know exact amounts\n /// @param stream [WrapToken, ArrayLength, ...[To, Amount][]]. An array of destinations and token amounts\n /// @return amountTotal Total amount distributed\n function wrapAndDistributeERC20Amounts(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n IWETH(token).deposit{value: address(this).balance}();\n uint8 num = stream.readUint8();\n amountTotal = 0;\n for (uint256 i = 0; i < num; ++i) {\n address to = stream.readAddress();\n uint256 amount = stream.readUint();\n amountTotal += amount;\n IERC20(token).safeTransfer(to, amount);\n }\n require(address(this).balance == 0, \"RouteProcessor: invalid input amount\");\n }\n\n /// @notice Distributes input BentoBox tokens from msg.sender to addresses. Tokens should be approved\n /// @notice Expected to be called for initial liquidity transfer from the user to pools, so we know exact amounts\n /// @param stream [ArrayLength, ...[To, ShareAmount][]]. An array of destinations and token share amounts\n /// @param token Token to distribute\n /// @return sharesTotal Total shares distributed\n function distributeBentoShares(uint256 stream, address token) private returns (uint256 sharesTotal) {\n uint8 num = stream.readUint8();\n sharesTotal = 0;\n for (uint256 i = 0; i < num; ++i) {\n address to = stream.readAddress();\n uint256 share = stream.readUint();\n sharesTotal += share;\n bentoBox.transfer(token, msg.sender, to, share);\n }\n }\n\n /// @notice Distributes ERC20 tokens from RouteProcessor to addresses\n /// @notice Quantity for sending is determined by share in 1/65535\n /// @notice During routing we can't predict in advance the actual value of internal swaps because of slippage,\n /// @notice so we have to work with shares - not fixed amounts\n /// @param stream [Token, ArrayLength, ...[To, ShareAmount][]]. Token to distribute. An array of destinations and token share amounts\n function distributeERC20Shares(uint256 stream) private {\n address token = stream.readAddress();\n uint8 num = stream.readUint8();\n uint256 amountTotal = IERC20(token).balanceOf(address(this))\n - 1; // slot undrain protection\n\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n address to = stream.readAddress();\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / 65535;\n amountTotal -= amount;\n IERC20(token).safeTransfer(to, amount);\n }\n }\n }\n\n /// @notice Distributes BentoBox tokens from RouteProcessor to addresses\n /// @notice Quantity for sending is determined by portions in 1/65535.\n /// @notice During routing we can't predict in advance the actual value of internal swaps because of slippage,\n /// @notice so we have to work with portions - not fixed amounts\n /// @param stream [Token, ArrayLength, ...[To, ShareAmount][]]. Token to distribute. An array of destinations and token share amounts\n function distributeBentoPortions(uint256 stream) private {\n address token = stream.readAddress();\n uint8 num = stream.readUint8();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this))\n - 1; // slot undrain protection\n\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n address to = stream.readAddress();\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / 65535;\n amountTotal -= amount;\n bentoBox.transfer(token, address(this), to, amount);\n }\n }\n }\n\n /// @notice Unwraps the Native Token\n /// @param receiver Destination of the unwrapped token\n /// @param stream [Token]. Token to unwrap native\n function unwrapNative(address receiver, uint256 stream) private {\n address token = stream.readAddress();\n IWETH(token).withdraw( IERC20(token).balanceOf(address(this))\n - 1); // slot undrain protection\n payable(receiver).transfer(address(this).balance);\n }\n}\n" + }, + "contracts/RouteProcessor3_1.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport './InputStream.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\n/// version 3.1\ncontract RouteProcessor3_1 is Ownable {\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint amountIn, \n uint amountOutMin,\n uint amountOut\n );\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = 1;\n uint8 private paused = 1;\n modifier lock() {\n require(unlocked == 1, 'RouteProcessor is locked');\n require(paused == 1, 'RouteProcessor is paused');\n unlocked = 2;\n _;\n unlocked = 1;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender] == true, \"RP: caller is not the owner or a priviledged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = 2;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = 1;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n (bool success, bytes memory returnBytes) = transferValueTo.call{value: amountValueTransfer}('');\n require(success, string(abi.encodePacked(returnBytes)));\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn == NATIVE_ADDRESS ? address(this).balance : IERC20(tokenIn).balanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut == NATIVE_ADDRESS ? address(to).balance : IERC20(tokenOut).balanceOf(to);\n\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) processMyERC20(stream);\n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) processNative(stream);\n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n }\n\n uint256 balanceInFinal = tokenIn == NATIVE_ADDRESS ? address(this).balance : IERC20(tokenIn).balanceOf(msg.sender);\n require(balanceInFinal + amountIn >= balanceInInitial, 'RouteProcessor: Minimal imput balance violation');\n\n uint256 balanceOutFinal = tokenOut == NATIVE_ADDRESS ? address(to).balance : IERC20(tokenOut).balanceOf(to);\n require(balanceOutFinal >= balanceOutInitial + amountOutMin, 'RouteProcessor: Minimal ouput balance violation');\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, amountIn, amountOutMin, amountOut);\n }\n\n function applyPermit(address tokenIn, uint256 stream) private {\n //address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s)\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed process program\n function processNative(uint256 stream) private {\n uint256 amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n function processMyERC20(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed process program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / 65535;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, address(this), token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint8 num = stream.readUint8();\n\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / 65535;\n amountTotal -= amount;\n swap(stream, address(this), token, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed process program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from != address(this)) IERC20(tokenIn).safeTransferFrom(from, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n payable(to).transfer(address(this).balance);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (amountIn != 0) {\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else IERC20(tokenIn).safeTransferFrom(from, address(bentoBox), amountIn);\n } else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (amountIn > 0) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n\n if (amountIn != 0) {\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else IERC20(tokenIn).safeTransferFrom(from, pool, amountIn);\n }\n // without 'else' in order to support tax tokens\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * 997;\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (amountIn != 0) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from != address(this)) {\n require(from == msg.sender, 'swapUniV3: unexpected from address');\n IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n }\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n\n // Normally, RouteProcessor shouldn't have any liquidity on board\n // If some liquidity exists, it is sweept by the next user that makes swap through these tokens\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n}\n" + }, + "contracts/RouteProcessor3_2.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport './InputStream.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\n/// version 3.2\ncontract RouteProcessor3_2 is Ownable {\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint amountIn, \n uint amountOutMin,\n uint amountOut\n );\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = 1;\n uint8 private paused = 1;\n modifier lock() {\n require(unlocked == 1, 'RouteProcessor is locked');\n require(paused == 1, 'RouteProcessor is paused');\n unlocked = 2;\n _;\n unlocked = 1;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender] == true, \"RP: caller is not the owner or a priviledged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = 2;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = 1;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n (bool success, bytes memory returnBytes) = transferValueTo.call{value: amountValueTransfer}('');\n require(success, string(abi.encodePacked(returnBytes)));\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn == NATIVE_ADDRESS ? address(this).balance : IERC20(tokenIn).balanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut == NATIVE_ADDRESS ? address(to).balance : IERC20(tokenOut).balanceOf(to);\n\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) processMyERC20(stream);\n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) processNative(stream);\n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n }\n\n uint256 balanceInFinal = tokenIn == NATIVE_ADDRESS ? address(this).balance : IERC20(tokenIn).balanceOf(msg.sender);\n require(balanceInFinal + amountIn >= balanceInInitial, 'RouteProcessor: Minimal imput balance violation');\n\n uint256 balanceOutFinal = tokenOut == NATIVE_ADDRESS ? address(to).balance : IERC20(tokenOut).balanceOf(to);\n require(balanceOutFinal >= balanceOutInitial + amountOutMin, 'RouteProcessor: Minimal ouput balance violation');\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, amountIn, amountOutMin, amountOut);\n }\n\n function applyPermit(address tokenIn, uint256 stream) private {\n //address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s)\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed process program\n function processNative(uint256 stream) private {\n uint256 amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n function processMyERC20(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed process program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / 65535;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, address(this), token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint8 num = stream.readUint8();\n\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / 65535;\n amountTotal -= amount;\n swap(stream, address(this), token, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed process program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from != address(this)) IERC20(tokenIn).safeTransferFrom(from, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n payable(to).transfer(address(this).balance);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (amountIn != 0) {\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else IERC20(tokenIn).safeTransferFrom(from, address(bentoBox), amountIn);\n } else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (amountIn > 0) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (amountIn != 0) {\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else IERC20(tokenIn).safeTransferFrom(from, pool, amountIn);\n }\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * 997;\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (amountIn != 0) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from != address(this)) {\n require(from == msg.sender, 'swapUniV3: unexpected from address');\n IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n }\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n\n // Normally, RouteProcessor shouldn't have any liquidity on board\n // If some liquidity exists, it is sweept by the next user that makes swap through these tokens\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n}\n" + }, + "contracts/RouteProcessor3.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport './InputStream.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\n/// version 2.1\ncontract RouteProcessor3 is Ownable {\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint amountIn, \n uint amountOutMin,\n uint amountOut\n );\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = 1;\n uint8 private paused = 1;\n modifier lock() {\n require(unlocked == 1, 'RouteProcessor is locked');\n require(paused == 1, 'RouteProcessor is paused');\n unlocked = 2;\n _;\n unlocked = 1;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender] == true, \"RP: caller is not the owner or a priviledged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = 2;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = 1;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n (bool success, bytes memory returnBytes) = transferValueTo.call{value: amountValueTransfer}('');\n require(success, string(abi.encodePacked(returnBytes)));\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn == NATIVE_ADDRESS ? address(this).balance : IERC20(tokenIn).balanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut == NATIVE_ADDRESS ? address(to).balance : IERC20(tokenOut).balanceOf(to);\n\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) processMyERC20(stream);\n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) processNative(stream);\n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n }\n\n uint256 balanceInFinal = tokenIn == NATIVE_ADDRESS ? address(this).balance : IERC20(tokenIn).balanceOf(msg.sender);\n require(balanceInFinal + amountIn >= balanceInInitial, 'RouteProcessor: Minimal imput balance violation');\n\n uint256 balanceOutFinal = tokenOut == NATIVE_ADDRESS ? address(to).balance : IERC20(tokenOut).balanceOf(to);\n require(balanceOutFinal >= balanceOutInitial + amountOutMin, 'RouteProcessor: Minimal ouput balance violation');\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, amountIn, amountOutMin, amountOut);\n }\n\n function applyPermit(address tokenIn, uint256 stream) private {\n //address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s)\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed process program\n function processNative(uint256 stream) private {\n uint256 amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n function processMyERC20(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed process program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / 65535;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, address(this), token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint8 num = stream.readUint8();\n\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / 65535;\n amountTotal -= amount;\n swap(stream, address(this), token, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed process program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from != address(this)) IERC20(tokenIn).safeTransferFrom(from, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n payable(to).transfer(address(this).balance);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (amountIn != 0) {\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else IERC20(tokenIn).safeTransferFrom(from, address(bentoBox), amountIn);\n } else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (amountIn > 0) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n\n if (amountIn != 0) {\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else IERC20(tokenIn).safeTransferFrom(from, pool, amountIn);\n } else amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * 997;\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (amountIn != 0) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from != address(this)) {\n require(from == msg.sender, 'swapUniV3: unexpected from address');\n IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n }\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n\n // Normally, RouteProcessor shouldn't have any liquidity on board\n // If some liquidity exists, it is sweept by the next user that makes swap through these tokens\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n}\n" + }, + "contracts/RouteProcessor4.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Approve.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor4 is Ownable {\n using SafeERC20 for IERC20;\n using Approve for IERC20;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n (bool success, bytes memory returnBytes) = transferValueTo.call{value: amountValueTransfer}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn == NATIVE_ADDRESS ? 0 : IERC20(tokenIn).balanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut == NATIVE_ADDRESS ? address(to).balance : IERC20(tokenOut).balanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn == NATIVE_ADDRESS ? 0 : IERC20(tokenIn).balanceOf(msg.sender);\n require(balanceInFinal + amountIn >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut == NATIVE_ADDRESS ? address(to).balance : IERC20(tokenOut).balanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n (bool success,)= payable(to).call{value: amountIn}(\"\");\n require(success, \"RouteProcessor.wrapNative: Native token transfer failed\");\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = IERC20(tokenOut).balanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = IERC20(tokenOut).balanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) { \n if(tokenOut == NATIVE_ADDRESS) {\n (bool success,)= payable(to).call{value: amountOut}(\"\");\n require(success, \"RouteProcessor.swapCurve: Native token transfer failed\");\n } else {\n IERC20(tokenOut).safeTransfer(to, amountOut);\n }\n }\n }\n}\n" + }, + "contracts/RouteProcessor5.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" + }, + "contracts/Utils.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "interfaces/IBentoBoxMinimal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" + }, + "interfaces/ICurve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" + }, + "interfaces/IPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" + }, + "interfaces/ITridentCLPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/boba/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json b/protocols/route-processor/deployments/boba/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json deleted file mode 100644 index 01826e7b93..0000000000 --- a/protocols/route-processor/deployments/boba/solcInputs/e556d43a3caf4f1fb4f12d632d103b28.json +++ /dev/null @@ -1,80 +0,0 @@ -{ - "language": "Solidity", - "sources": { - "@openzeppelin/contracts/access/Ownable.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" - }, - "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" - }, - "@openzeppelin/contracts/token/ERC20/IERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" - }, - "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" - }, - "@openzeppelin/contracts/utils/Address.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" - }, - "@openzeppelin/contracts/utils/Context.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" - }, - "contracts/InputStream.sol": { - "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" - }, - "contracts/RouteProcessor5.sol": { - "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" - }, - "contracts/Utils.sol": { - "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" - }, - "interfaces/IBentoBoxMinimal.sol": { - "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" - }, - "interfaces/ICurve.sol": { - "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" - }, - "interfaces/IPool.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" - }, - "interfaces/ITridentCLPool.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" - }, - "interfaces/IUniswapV2Pair.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" - }, - "interfaces/IUniswapV3Pool.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" - }, - "interfaces/IWETH.sol": { - "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" - } - }, - "settings": { - "optimizer": { - "enabled": true, - "runs": 10000000 - }, - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "devdoc", - "userdoc", - "storageLayout", - "evm.gasEstimates" - ], - "": [ - "ast" - ] - } - }, - "metadata": { - "useLiteralContent": true - } - } -} \ No newline at end of file From e3fca1cf10835186a18188d4106d6dd00802d30c Mon Sep 17 00:00:00 2001 From: 0xMasayoshi <0xMasayoshi@protonmail.com> Date: Thu, 1 Aug 2024 11:52:32 +0700 Subject: [PATCH 013/125] chore: update RP5 config --- packages/sushi/src/config/route-processor.ts | 83 ++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/packages/sushi/src/config/route-processor.ts b/packages/sushi/src/config/route-processor.ts index 65e2fee9cb..041149ccfa 100644 --- a/packages/sushi/src/config/route-processor.ts +++ b/packages/sushi/src/config/route-processor.ts @@ -341,3 +341,86 @@ export const isRouteProcessor4ChainId = ( ROUTE_PROCESSOR_4_SUPPORTED_CHAIN_IDS.includes( chainId as RouteProcessor4ChainId, ) + +// v5 +export const ROUTE_PROCESSOR_5_SUPPORTED_CHAIN_IDS = [ + ChainId.ETHEREUM, + ChainId.ARBITRUM, + ChainId.OPTIMISM, + ChainId.BASE, + ChainId.POLYGON, + ChainId.AVALANCHE, + ChainId.BSC, + ChainId.LINEA, + ChainId.ARBITRUM_NOVA, + ChainId.GNOSIS, + ChainId.FANTOM, + ChainId.BTTC, + ChainId.CELO, + ChainId.FILECOIN, + ChainId.HAQQ, + ChainId.KAVA, + ChainId.METIS, + ChainId.THUNDERCORE, + ChainId.SCROLL, + ChainId.ZETACHAIN, + ChainId.MOONBEAM, + ChainId.MOONRIVER, + ChainId.POLYGON_ZKEVM, + ChainId.FUSE, + ChainId.HARMONY, + ChainId.TELOS, + ChainId.BOBA, + ChainId.BOBA_BNB, + ChainId.CORE, + ChainId.CRONOS, + ChainId.BLAST, + ChainId.SKALE_EUROPA, + ChainId.ROOTSTOCK, +] as const +export type RouteProcessor5ChainId = + (typeof ROUTE_PROCESSOR_5_SUPPORTED_CHAIN_IDS)[number] +export const ROUTE_PROCESSOR_5_ADDRESS: Record< + RouteProcessor5ChainId, + `0x${string}` +> = { + [ChainId.ETHEREUM]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [ChainId.ARBITRUM]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [ChainId.OPTIMISM]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [ChainId.BASE]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [ChainId.POLYGON]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [ChainId.AVALANCHE]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [ChainId.BSC]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [ChainId.LINEA]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [ChainId.ARBITRUM_NOVA]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [ChainId.GNOSIS]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [ChainId.FANTOM]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [ChainId.BTTC]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [ChainId.CELO]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [ChainId.FILECOIN]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [ChainId.HAQQ]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [ChainId.KAVA]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [ChainId.METIS]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [ChainId.THUNDERCORE]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [ChainId.SCROLL]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [ChainId.ZETACHAIN]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [ChainId.MOONBEAM]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [ChainId.MOONRIVER]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [ChainId.POLYGON_ZKEVM]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [ChainId.FUSE]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [ChainId.HARMONY]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [ChainId.TELOS]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [ChainId.BOBA]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [ChainId.BOBA_BNB]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [ChainId.CORE]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [ChainId.CRONOS]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [ChainId.BLAST]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [ChainId.SKALE_EUROPA]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', + [ChainId.ROOTSTOCK]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', +} as const +export const isRouteProcessor5ChainId = ( + chainId: ChainId, +): chainId is RouteProcessor5ChainId => + ROUTE_PROCESSOR_5_SUPPORTED_CHAIN_IDS.includes( + chainId as RouteProcessor5ChainId, + ) From 31286ffb2709a0faa069923afb5528ca061e08bd Mon Sep 17 00:00:00 2001 From: 0xMasayoshi <0xMasayoshi@protonmail.com> Date: Thu, 1 Aug 2024 17:46:57 +0700 Subject: [PATCH 014/125] fix: lint --- protocols/route-processor/deploy/RouteProcessor5.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/protocols/route-processor/deploy/RouteProcessor5.ts b/protocols/route-processor/deploy/RouteProcessor5.ts index 565074158d..0e455c558b 100644 --- a/protocols/route-processor/deploy/RouteProcessor5.ts +++ b/protocols/route-processor/deploy/RouteProcessor5.ts @@ -3,7 +3,6 @@ import { HardhatRuntimeEnvironment } from 'hardhat/types' const func: DeployFunction = async ({ ethers, - getNamedSigners, deployments, run, }: HardhatRuntimeEnvironment) => { From ec856f635f44ec043c6d495c2c30385d6f0f566f Mon Sep 17 00:00:00 2001 From: Ilya Lyalin Date: Thu, 1 Aug 2024 18:24:00 +0300 Subject: [PATCH 015/125] feat: routeProcessor5Params +[enum ProcessFunction] --- packages/sushi/src/router/router.ts | 78 ++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-) diff --git a/packages/sushi/src/router/router.ts b/packages/sushi/src/router/router.ts index 625be690bf..e9601ac020 100644 --- a/packages/sushi/src/router/router.ts +++ b/packages/sushi/src/router/router.ts @@ -6,6 +6,7 @@ import { } from 'viem' import { routeProcessor2Abi } from '../abi/routeProcessor2Abi.js' import { routeProcessor4Abi } from '../abi/routeProcessor4Abi.js' +import { routeProcessor5Abi } from '../abi/routeProcessor5Abi.js' import { routeProcessorAbi } from '../abi/routeProcessorAbi.js' import { ChainId } from '../chain/index.js' import { ADDITIONAL_BASES } from '../config/additional-bases.js' @@ -34,6 +35,13 @@ import { import { getRouteProcessor4Code } from './tines-to-route-processor-4.js' import { getRouteProcessorCode } from './tines-to-route-processor.js' +export enum ProcessFunction { + ProcessRoute = 0, + TransferValueAndprocessRoute = 1, + ProcessRouteWithTransferValueInput = 2, + ProcessRouteWithTransferValueOutput = 3, +} + function TokenToRToken(t: Type): RToken { if (t instanceof Token) return t as RToken const nativeRToken: RToken = { @@ -58,6 +66,24 @@ const RP4processRouteEncodeData = prepareEncodeFunctionData({ abi: routeProcessor4Abi, functionName: 'processRoute', }) +const RP5processRouteEncodeData = [ + prepareEncodeFunctionData({ + abi: routeProcessor5Abi, + functionName: 'processRoute', + }), + prepareEncodeFunctionData({ + abi: routeProcessor5Abi, + functionName: 'transferValueAndprocessRoute', + }), + prepareEncodeFunctionData({ + abi: routeProcessor5Abi, + functionName: 'processRouteWithTransferValueInput', + }), + prepareEncodeFunctionData({ + abi: routeProcessor5Abi, + functionName: 'processRouteWithTransferValueOutput', + }), +] const isWrap = ({ fromToken, toToken }: { fromToken: Type; toToken: Type }) => fromToken.isNative && @@ -371,7 +397,57 @@ export class Router { } } - static routeProcessor5Params = this.routeProcessor4Params + // the same as routeProcessor4Params, but with processFunction + static routeProcessor5Params( + poolCodesMap: Map, + route: MultiRoute, + fromToken: Type, + toToken: Type, + to: Address, + RPAddr: Address, + permits: PermitData[] = [], + maxPriceImpact = 0.005, + source = RouterLiquiditySource.Sender, + processFunction = ProcessFunction.ProcessRoute, + ): RPParams { + const tokenIn = + fromToken instanceof Token + ? (fromToken.address as Address) + : '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE' + const tokenOut = + toToken instanceof Token + ? (toToken.address as Address) + : '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE' + const isWrapOrUnwap = + isWrap({ fromToken, toToken }) || isUnwrap({ fromToken, toToken }) + const amountOutMin = isWrapOrUnwap + ? route.amountInBI + : (route.amountOutBI * getBigInt((1 - maxPriceImpact) * 1_000_000)) / + 1_000_000n + + const routeCode = getRouteProcessor4Code( + route, + RPAddr, + to, + poolCodesMap, + permits, + source, + ) as Hex + const data = encodeFunctionData({ + ...RP5processRouteEncodeData[processFunction], + args: [tokenIn, route.amountInBI, tokenOut, amountOutMin, to, routeCode], + }) + return { + tokenIn, + amountIn: route.amountInBI, + tokenOut, + amountOutMin, + to, + routeCode, + data, + value: fromToken instanceof Token ? undefined : route.amountInBI, + } + } // Human-readable route printing static routeToHumanString( From 7df042677a415807f0134038fb0253bfe3ec72be Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Thu, 1 Aug 2024 16:55:09 +0100 Subject: [PATCH 016/125] fix: ensure free is avail --- Dockerfile.extractor | 2 ++ Dockerfile.router | 2 ++ 2 files changed, 4 insertions(+) diff --git a/Dockerfile.extractor b/Dockerfile.extractor index 97e62f6394..876765393c 100644 --- a/Dockerfile.extractor +++ b/Dockerfile.extractor @@ -15,6 +15,8 @@ RUN corepack enable WORKDIR /app +RUN apt-get install procps -y + # RUN pnpm install turbo --global COPY apis/extractor apis/extractor diff --git a/Dockerfile.router b/Dockerfile.router index d4f28ad7d5..6aa796731d 100644 --- a/Dockerfile.router +++ b/Dockerfile.router @@ -15,6 +15,8 @@ RUN corepack enable WORKDIR /app +RUN apt-get install procps -y + # RUN pnpm install turbo --global COPY apis/router apis/router From 00ae556b086a1c29cb9577c7f4bf9c4f7ca3061e Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Thu, 1 Aug 2024 16:59:42 +0100 Subject: [PATCH 017/125] fix: dont use free --- Dockerfile.extractor | 6 +++--- Dockerfile.router | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Dockerfile.extractor b/Dockerfile.extractor index 876765393c..a89195e8ea 100644 --- a/Dockerfile.extractor +++ b/Dockerfile.extractor @@ -15,8 +15,6 @@ RUN corepack enable WORKDIR /app -RUN apt-get install procps -y - # RUN pnpm install turbo --global COPY apis/extractor apis/extractor @@ -41,4 +39,6 @@ EXPOSE 80 ENV NODE_ENV=production -CMD NODE_OPTIONS=--max-old-space-size=$(expr $(echo "$(free -m)" | awk '/^Mem:/ {print $2}') - 512) node /app/apis/extractor/dist/index.js \ No newline at end of file +CMD NODE_OPTIONS=--max-old-space-size=7680 node /app/apis/extractor/dist/index.js + +# CMD NODE_OPTIONS=--max-old-space-size=$(expr $(echo "$(free -m)" | awk '/^Mem:/ {print $2}') - 512) node /app/apis/extractor/dist/index.js \ No newline at end of file diff --git a/Dockerfile.router b/Dockerfile.router index 6aa796731d..bfd714299f 100644 --- a/Dockerfile.router +++ b/Dockerfile.router @@ -15,8 +15,6 @@ RUN corepack enable WORKDIR /app -RUN apt-get install procps -y - # RUN pnpm install turbo --global COPY apis/router apis/router @@ -41,4 +39,6 @@ EXPOSE 80 ENV NODE_ENV=production -CMD NODE_OPTIONS=--max-old-space-size=$(expr $(echo "$(free -m)" | awk '/^Mem:/ {print $2}') - 512) node /app/apis/router/dist/index.js \ No newline at end of file +CMD NODE_OPTIONS=--max-old-space-size=1536 node /app/apis/router/dist/index.js + +# CMD NODE_OPTIONS=--max-old-space-size=$(expr $(echo "$(free -m)" | awk '/^Mem:/ {print $2}') - 512) node /app/apis/router/dist/index.js \ No newline at end of file From a5353bf3b2afb501d459675ac823a8be258c0231 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Fri, 2 Aug 2024 09:10:52 +0100 Subject: [PATCH 018/125] feat: begin v5 api --- apis/router/src/handlers/swap2/index.ts | 22 ++--- apis/router/src/handlers/swap2/schema.ts | 17 +++- apis/router/src/index.ts | 6 +- packages/sushi/src/router/makeAPI02Object.ts | 93 +++++--------------- 4 files changed, 47 insertions(+), 91 deletions(-) diff --git a/apis/router/src/handlers/swap2/index.ts b/apis/router/src/handlers/swap2/index.ts index 01e9139650..c22328e040 100644 --- a/apis/router/src/handlers/swap2/index.ts +++ b/apis/router/src/handlers/swap2/index.ts @@ -156,14 +156,7 @@ const handler = ( ) : undefined - const json = makeAPI03Object( - bestRoute, - rpParams, - routeProcessorAddress, - poolCodesMap, - ) - - // we want to return { route, tx: { from, to, gas, gasPrice, data, value, } } + const json = makeAPI03Object(bestRoute, rpParams, routeProcessorAddress) swapRequestStatistics.requestWasProcessed(statistics, tokensAreKnown) return res.json(json) @@ -174,18 +167,17 @@ const handler = ( const data: { error: string | string[] | undefined - params: z.infer | undefined - route: MultiRoute | undefined + params: z.infer | undefined + route: ReturnType | undefined } = { - error: e instanceof Error ? e.stack?.split('\n') : `${e}`, + error: undefined, params: undefined, route: undefined, } try { data.error = e instanceof Error ? e.stack?.split('\n') : `${e}` if (parsed.data) data.params = parsed.data - if (bestRoute) - data.route = makeAPI03Object(bestRoute, undefined, '', poolCodesMap) + if (bestRoute) data.route = makeAPI03Object(bestRoute, undefined, '') } catch (_e) {} Logger.error(CHAIN_ID, 'Routing crashed', safeSerialize(data), false) @@ -195,8 +187,8 @@ const handler = ( } } -export const swapV4_2 = handler( - querySchema4_2, +export const swapV5 = handler( + querySchema5, Router.routeProcessor4Params, ROUTE_PROCESSOR_4_ADDRESS[CHAIN_ID], ) diff --git a/apis/router/src/handlers/swap2/schema.ts b/apis/router/src/handlers/swap2/schema.ts index 81ffda150f..cb01631ee6 100644 --- a/apis/router/src/handlers/swap2/schema.ts +++ b/apis/router/src/handlers/swap2/schema.ts @@ -6,6 +6,7 @@ import z from 'zod' // Swap 2.0 // maxPriceImpact - max current price impact (during route planning). Default - no control // maxSlippage - max slippage (during route processing). Default - 0.5% + export const querySchema5 = z.object({ tokenIn: z.custom
( (val) => isAddressFast(val), @@ -36,15 +37,25 @@ export const querySchema5 = z.object({ z.coerce .number() .lt(1, 'maxPriceImpact should be lesser than 1') - .gt(0, 'maxPriceImpact should be positive'), + .positive(), ), maxSlippage: z.coerce .number() .lt(1, 'maxSlippage should be lesser than 1') - .gt(0, 'maxSlippage should be positive') + .positive() .default(0.005), // includeRoute: z.boolean().default(true), // includeTx: z.boolean().default(true), + enableFee: z.boolean().default(true), + feeReceiver: z.custom
( + (val) => isAddressFast(val), + (val) => ({ message: `Incorrect fee receiver address: ${val}` }), + ), + feeAmount: z.coerce + .number() + .lte(0.003, 'feeAmount should be less than or equal to 0.003') + .positive() + .default(0.0025), }) -export type querySchema4_2 = z.infer +export type querySchema5 = z.infer diff --git a/apis/router/src/index.ts b/apis/router/src/index.ts index 2f00cb8c5e..ddbd904b5a 100644 --- a/apis/router/src/index.ts +++ b/apis/router/src/index.ts @@ -21,7 +21,7 @@ import { import { CPUUsageStatistics } from './cpu-usage-statistics.js' import { priceByAddressHandler, pricesHandler } from './handlers/price/index.js' import { swapV3_2, swapV4 } from './handlers/swap/index.js' -import { swapV4_2 } from './handlers/swap2/index.js' +import { swapV5 } from './handlers/swap2/index.js' import tokenHandler from './handlers/token/index.js' import { updatePrices } from './prices.js' @@ -118,8 +118,8 @@ async function start() { app.get(`/swap/v4/${CHAIN_ID}`, (req, res) => { return swapV4(client)(req, res) }) - app.get(`/swap/v4_2/${CHAIN_ID}`, (req, res) => { - return swapV4_2(client)(req, res) + app.get(`/swap/v5/${CHAIN_ID}`, (req, res) => { + return swapV5(client)(req, res) }) app.get(`/token/v1/${CHAIN_ID}/:address`, tokenHandler(client)) diff --git a/packages/sushi/src/router/makeAPI02Object.ts b/packages/sushi/src/router/makeAPI02Object.ts index 109beae083..0bd1f5971f 100644 --- a/packages/sushi/src/router/makeAPI02Object.ts +++ b/packages/sushi/src/router/makeAPI02Object.ts @@ -1,4 +1,3 @@ -import { Token } from '../currency/token.js' import { type MultiRoute, type RToken, @@ -6,7 +5,6 @@ import { RouteStatus, } from '../tines/index.js' import { LiquidityProviders } from './liquidity-providers/LiquidityProvider.js' -import { PoolCode } from './pool-codes/PoolCode.js' import type { RPParams } from './router.js' function makeAPI02Token(token: RToken) { @@ -35,22 +33,6 @@ function makeAPI02Leg(leg: RouteLeg, tokens: TokenConvertor) { } } -function makeAPI03Leg( - leg: RouteLeg, - tokens: TokenConvertor, - liquidityProviders: LiquidityProviderConvertor, -) { - return { - liquidityProvider: liquidityProviders.getLiquidityProviderIndex( - leg.uniqueId, - ), - poolAddress: leg.poolAddress, - tokenFrom: tokens.getTokenIndex(leg.tokenFrom), - tokenTo: tokens.getTokenIndex(leg.tokenTo), - share: leg.absolutePortion, - } -} - class TokenConvertor { tokens: RToken[] = [] tokenMap = new Map() @@ -75,32 +57,6 @@ class TokenConvertor { } } -class LiquidityProviderConvertor { - liquidityProviders: LiquidityProviders[] = [] - liquidityProviderMap = new Map() - idToLiquidityProvider = new Map() - - addLiquidityProvider(id: string, liquidityProvider: LiquidityProviders) { - if (this.liquidityProviderMap.get(liquidityProvider) === undefined) { - this.liquidityProviders.push(liquidityProvider) - - this.liquidityProviderMap.set( - liquidityProvider, - this.liquidityProviders.length - 1, - ) - } - this.idToLiquidityProvider.set(id, liquidityProvider) - } - - getLiquidityProviderIndex(id: string) { - return this.liquidityProviderMap.get(this.idToLiquidityProvider.get(id)!) - } - - geLiquidityProviderList() { - return this.liquidityProviders - } -} - export function makeAPI02Object( route: MultiRoute, rpParams: RPParams | undefined, @@ -150,28 +106,22 @@ export function makeAPI03Object( route: MultiRoute, rpParams: RPParams | undefined, routeProcessorAddr: string, - poolCodesMap: Map, + debug = false, ) { if (route.status === RouteStatus.NoWay) return { status: RouteStatus.NoWay } const tokens = new TokenConvertor() - const liquidityProviders = new LiquidityProviderConvertor() route.legs.forEach((l) => { tokens.addToken(l.tokenFrom) tokens.addToken(l.tokenTo) - liquidityProviders.addLiquidityProvider( - l.uniqueId, - poolCodesMap.get(l.uniqueId)!.liquidityProvider, - ) }) - const APIObj = { + return { status: route.status, tokens: tokens.getTokenList(), - liquidityProviders: liquidityProviders.geLiquidityProviderList(), tokenFrom: tokens.getTokenIndex(route.fromToken), tokenTo: tokens.getTokenIndex(route.toToken), - primaryPrice: route.primaryPrice, + primaryPrice: debug ? route.primaryPrice : undefined, swapPrice: route.swapPrice, priceImpact: route.priceImpact, @@ -179,22 +129,25 @@ export function makeAPI03Object( assumedAmountOut: route.amountOutBI.toString(), gasSpent: route.gasSpent, - route: route.legs.map((l) => makeAPI03Leg(l, tokens, liquidityProviders)), - } as any - if (rpParams !== undefined) { - APIObj.routeProcessorAddr = routeProcessorAddr - APIObj.routeProcessorArgs = { - tokenIn: rpParams.tokenIn, - amountIn: rpParams.amountIn.toString(), - tokenOut: rpParams.tokenOut, - amountOutMin: rpParams.amountOutMin.toString(), - to: rpParams.to, - routeCode: rpParams.routeCode, - txdata: rpParams.data, - } - if (rpParams.value !== undefined) - APIObj.routeProcessorArgs.value = rpParams.value.toString() - } + route: route.legs.map((l) => makeAPI02Leg(l, tokens)), - return APIObj + // we want to return { route, tx: { from, to, gas, gasPrice, data, value, } } + + tx: + rpParams !== undefined + ? { + from: rpParams.to, + to: routeProcessorAddr, + // we could include a simulation of gas usage + // gas: rpParams.gas, + // we could include a gas price estimatation + // gasPrice: rpParams.gasPrice, + data: rpParams.data, + value: + rpParams.value !== undefined + ? rpParams.value.toString() + : undefined, + } + : undefined, + } } From 17cc644a3249c0a97b2ef2250e68350268258b45 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Fri, 2 Aug 2024 10:35:17 +0100 Subject: [PATCH 019/125] chore: rp5 address and params --- apis/router/src/handlers/swap2/index.ts | 13 ++- k8s/chart/values.yaml | 128 ++++++++++++------------ packages/sushi/src/router/router.ts | 5 +- 3 files changed, 76 insertions(+), 70 deletions(-) diff --git a/apis/router/src/handlers/swap2/index.ts b/apis/router/src/handlers/swap2/index.ts index c22328e040..363dbfd722 100644 --- a/apis/router/src/handlers/swap2/index.ts +++ b/apis/router/src/handlers/swap2/index.ts @@ -1,11 +1,12 @@ import { Logger, safeSerialize } from '@sushiswap/extractor' import { Request, Response } from 'express' import { ChainId } from 'sushi/chain' -import { ROUTE_PROCESSOR_4_ADDRESS } from 'sushi/config' +import { ROUTE_PROCESSOR_5_ADDRESS } from 'sushi/config' import { Type } from 'sushi/currency' import { NativeWrapProvider, PoolCode, + ProcessFunction, Router, RouterLiquiditySource, makeAPI03Object, @@ -44,7 +45,7 @@ async function processUnknownToken( const handler = ( querySchema: typeof querySchema5, - routeProcessorParams: typeof Router.routeProcessor4Params, + routeProcessorParams: typeof Router.routeProcessor5Params, routeProcessorAddress: Address, ) => { return (client: ExtractorClient) => { @@ -75,6 +76,7 @@ const handler = ( preferSushi, maxPriceImpact, maxSlippage, + enableFee, } = parsed.data if ( client.lastUpdatedTimestamp + MAX_TIME_WITHOUT_NETWORK_UPDATE < @@ -153,6 +155,9 @@ const handler = ( [], maxSlippage, source ?? RouterLiquiditySource.Sender, + enableFee + ? ProcessFunction.ProcessRouteWithTransferValueOutput + : ProcessFunction.ProcessRoute, ) : undefined @@ -189,6 +194,6 @@ const handler = ( export const swapV5 = handler( querySchema5, - Router.routeProcessor4Params, - ROUTE_PROCESSOR_4_ADDRESS[CHAIN_ID], + Router.routeProcessor5Params, + ROUTE_PROCESSOR_5_ADDRESS[CHAIN_ID], ) diff --git a/k8s/chart/values.yaml b/k8s/chart/values.yaml index 973c0d0082..1416eee395 100644 --- a/k8s/chart/values.yaml +++ b/k8s/chart/values.yaml @@ -2,67 +2,67 @@ chains: - name: "ethereum" id: "1" - # - name: "optimism" - # id: "10" - # - name: "cronos" - # id: "25" - # - name: "rootstock" - # id: "30" - # - name: "telos" - # id: "40" - # - name: "bsc" - # id: "56" - # - name: "gnosis" - # id: "100" - # - name: "thundercore" - # id: "108" - # - name: "fuse" - # id: "122" - # - name: "polygon" - # id: "137" - # - name: "bttc" - # id: "199" - # - name: "fantom" - # id: "250" - # - name: "boba" - # id: "288" - # - name: "filecoin" - # id: "314" - # - name: "polygon-zkevm" - # id: "1101" - # - name: "core" - # id: "1116" - # - name: "moonbeam" - # id: "1284" - # - name: "moonriver" - # id: "1285" - # - name: "metis" - # id: "1088" - # - name: "kava" - # id: "2222" - # - name: "zetachain" - # id: "7000" - # - name: "base" - # id: "8453" - # - name: "haqq" - # id: "11235" - # - name: "arbitrum" - # id: "42161" - # - name: "arbitrum-nova" - # id: "42170" - # - name: "celo" - # id: "42220" - # - name: "avalanche" - # id: "43114" - # - name: "linea" - # id: "59144" - # - name: "boba-bnb" - # id: "56288" - # - name: "blast" - # id: "81457" - # - name: "scroll" - # id: "534352" - # - name: "harmony" - # id: "1666600000" - # - name: "skale-europa" - # id: "2046399126" \ No newline at end of file + - name: "optimism" + id: "10" + - name: "cronos" + id: "25" + - name: "rootstock" + id: "30" + - name: "telos" + id: "40" + - name: "bsc" + id: "56" + - name: "gnosis" + id: "100" + - name: "thundercore" + id: "108" + - name: "fuse" + id: "122" + - name: "polygon" + id: "137" + - name: "bttc" + id: "199" + - name: "fantom" + id: "250" + - name: "boba" + id: "288" + - name: "filecoin" + id: "314" + - name: "polygon-zkevm" + id: "1101" + - name: "core" + id: "1116" + - name: "moonbeam" + id: "1284" + - name: "moonriver" + id: "1285" + - name: "metis" + id: "1088" + - name: "kava" + id: "2222" + - name: "zetachain" + id: "7000" + - name: "base" + id: "8453" + - name: "haqq" + id: "11235" + - name: "arbitrum" + id: "42161" + - name: "arbitrum-nova" + id: "42170" + - name: "celo" + id: "42220" + - name: "avalanche" + id: "43114" + - name: "linea" + id: "59144" + - name: "boba-bnb" + id: "56288" + - name: "blast" + id: "81457" + - name: "scroll" + id: "534352" + - name: "harmony" + id: "1666600000" + - name: "skale-europa" + id: "2046399126" \ No newline at end of file diff --git a/packages/sushi/src/router/router.ts b/packages/sushi/src/router/router.ts index 769f0ac434..d375a26cf9 100644 --- a/packages/sushi/src/router/router.ts +++ b/packages/sushi/src/router/router.ts @@ -409,7 +409,7 @@ export class Router { to: Address, RPAddr: Address, permits: PermitData[] = [], - maxPriceImpact = 0.005, + maxSlippage = 0.005, source = RouterLiquiditySource.Sender, processFunction = ProcessFunction.ProcessRoute, ): RPParams { @@ -425,7 +425,7 @@ export class Router { isWrap({ fromToken, toToken }) || isUnwrap({ fromToken, toToken }) const amountOutMin = isWrapOrUnwap ? route.amountInBI - : (route.amountOutBI * getBigInt((1 - maxPriceImpact) * 1_000_000)) / + : (route.amountOutBI * getBigInt((1 - maxSlippage) * 1_000_000)) / 1_000_000n const routeCode = getRouteProcessor4Code( @@ -436,6 +436,7 @@ export class Router { permits, source, ) as Hex + const data = encodeFunctionData({ ...RP5processRouteEncodeData[processFunction], args: [tokenIn, route.amountInBI, tokenOut, amountOutMin, to, routeCode], From 76fdb6439b5558958aab828536b4005a33184ff7 Mon Sep 17 00:00:00 2001 From: 0xMasayoshi <0xMasayoshi@protonmail.com> Date: Fri, 2 Aug 2024 18:59:23 +0700 Subject: [PATCH 020/125] chore: add multisig map to config --- packages/sushi/src/config/wallet.ts | 72 +++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 packages/sushi/src/config/wallet.ts diff --git a/packages/sushi/src/config/wallet.ts b/packages/sushi/src/config/wallet.ts new file mode 100644 index 0000000000..16ae93542e --- /dev/null +++ b/packages/sushi/src/config/wallet.ts @@ -0,0 +1,72 @@ +import { ChainId } from '../chain/index.js' + +export const MULTISIG_CHAIN_IDS = [ + ChainId.ARBITRUM, + ChainId.AVALANCHE, + ChainId.BASE, + ChainId.BLAST, + ChainId.BOBA, + ChainId.BOBA_BNB, + ChainId.BSC, + ChainId.BTTC, + ChainId.CELO, + ChainId.CORE, + ChainId.ETHEREUM, + ChainId.FANTOM, + ChainId.FUSE, + ChainId.GNOSIS, + ChainId.HAQQ, + ChainId.HARMONY, + ChainId.KAVA, + ChainId.LINEA, + ChainId.METIS, + ChainId.MOONBEAM, + ChainId.MOONRIVER, + ChainId.OPTIMISM, + ChainId.POLYGON, + ChainId.POLYGON_ZKEVM, + ChainId.ROOTSTOCK, + ChainId.SCROLL, + ChainId.SKALE_EUROPA, + ChainId.TELOS, + ChainId.ZETACHAIN, +] as const + +export type MultisigChainId = (typeof MULTISIG_CHAIN_IDS)[number] + +export const MULTISIG_ADDRESS: Record = { + [ChainId.ARBITRUM]: '0x978982772b8e4055B921bf9295c0d74eB36Bc54e', + [ChainId.AVALANCHE]: '0x09842Ce338647906B686aBB3B648A6457fbB25DA', + [ChainId.BASE]: '0xFcD4e19Dd044cBa929cF1EEfc1C181aE4f5beCe8', + [ChainId.BLAST]: '0xbfF76182457256808BD11B0cAFc05C35c9E4aa43', + [ChainId.BOBA]: '0x3a131cd0A0F82c9610d7a90bBD4A924B1ccaa38E', + [ChainId.BOBA_BNB]: '0xb8f2faca5b2EBcd6Be7B5D9E164962dE9CCc3B76', + [ChainId.BSC]: '0xc6fD91aD4919Fd91e2c84077ba648092cB499638', + [ChainId.BTTC]: '0x488398D8EfeF84Bd3271f13ae8Eb44Cd2C1eE687', + [ChainId.CELO]: '0x751b01Fa14fD9640a1DF9014e2D0f3a03A198b81', + [ChainId.CORE]: '0x9ffC84bc9Cf7c85E4E6e2B0aB67BB6c643cA72A2', + [ChainId.ETHEREUM]: '0x19B3Eb3Af5D93b77a5619b047De0EED7115A19e7', + [ChainId.FANTOM]: '0xF9E7d4c6d36ca311566f46c81E572102A2DC9F52', + [ChainId.FUSE]: '0x33b6beb37837459Ee84a1Ffed2C6a4ca22e5F316', + [ChainId.GNOSIS]: '0xc375411C6597F692Add6a7a3AD5b3C38626B0F26', + [ChainId.HAQQ]: '0x43a3f312c749B5D23Fc9547c39478b83b39362aA', + [ChainId.HARMONY]: '0x30af69A3f4a6f266961313Ce0943719dF4A8AA10', + [ChainId.KAVA]: '0xb8f2faca5b2EBcd6Be7B5D9E164962dE9CCc3B76', + [ChainId.LINEA]: '0x9ffC84bc9Cf7c85E4E6e2B0aB67BB6c643cA72A2', + [ChainId.METIS]: '0xb8f2faca5b2EBcd6Be7B5D9E164962dE9CCc3B76', + [ChainId.MOONBEAM]: '0x9ffC84bc9Cf7c85E4E6e2B0aB67BB6c643cA72A2', + [ChainId.MOONRIVER]: '0x939f7E76cc515cc296dD3ce362D9a52e148A7D5f', + [ChainId.OPTIMISM]: '0x1219Bfa3A499548507b4917E33F17439b67A2177', + [ChainId.POLYGON]: '0x850a57630A2012B2494779fBc86bBc24F2a7baeF', + [ChainId.POLYGON_ZKEVM]: '0x9ffC84bc9Cf7c85E4E6e2B0aB67BB6c643cA72A2', + [ChainId.ROOTSTOCK]: '0x9ffC84bc9Cf7c85E4E6e2B0aB67BB6c643cA72A2', + [ChainId.SCROLL]: '0x9ffC84bc9Cf7c85E4E6e2B0aB67BB6c643cA72A2', + [ChainId.SKALE_EUROPA]: '0xa88a0398C8D8B34Ab3f19CbBAbc2C4F33149Dfa6', + [ChainId.TELOS]: '0x72840af61A60B585064c16Ee402B3823366823Cb', + [ChainId.ZETACHAIN]: '0xb8f2faca5b2EBcd6Be7B5D9E164962dE9CCc3B76', +} as const + +export const isMultisigChainId = ( + chainId: ChainId, +): chainId is MultisigChainId => + MULTISIG_CHAIN_IDS.includes(chainId as MultisigChainId) From 81e3e9deaaf799958af78db0645b38f34498e62f Mon Sep 17 00:00:00 2001 From: Ilya Lyalin Date: Fri, 2 Aug 2024 15:09:43 +0300 Subject: [PATCH 021/125] fix: additional params for nort processRoute functions --- packages/sushi/src/router/router.ts | 35 +++++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 4 deletions(-) diff --git a/packages/sushi/src/router/router.ts b/packages/sushi/src/router/router.ts index e9601ac020..f7cc3d14c7 100644 --- a/packages/sushi/src/router/router.ts +++ b/packages/sushi/src/router/router.ts @@ -409,6 +409,8 @@ export class Router { maxPriceImpact = 0.005, source = RouterLiquiditySource.Sender, processFunction = ProcessFunction.ProcessRoute, + transferValueTo?: Address, + amountValueTransfer?: bigint, ): RPParams { const tokenIn = fromToken instanceof Token @@ -433,10 +435,35 @@ export class Router { permits, source, ) as Hex - const data = encodeFunctionData({ - ...RP5processRouteEncodeData[processFunction], - args: [tokenIn, route.amountInBI, tokenOut, amountOutMin, to, routeCode], - }) + + let data: Hex + if (processFunction === ProcessFunction.ProcessRoute) { + data = encodeFunctionData({ + ...RP5processRouteEncodeData[processFunction], + args: [ + tokenIn, + route.amountInBI, + tokenOut, + amountOutMin, + to, + routeCode, + ], + }) + } else { + data = encodeFunctionData({ + ...RP5processRouteEncodeData[processFunction], + args: [ + transferValueTo, + amountValueTransfer, + tokenIn, + route.amountInBI, + tokenOut, + amountOutMin, + to, + routeCode, + ], + }) + } return { tokenIn, amountIn: route.amountInBI, From 6445a9fc7260359769190e6a94a83b3ccb1314b4 Mon Sep 17 00:00:00 2001 From: LufyCZ Date: Sat, 3 Aug 2024 12:17:14 +0000 Subject: [PATCH 022/125] refactor(pkgs/ui): navigation --- apps/tron/src/app/header.tsx | 4 +- apps/web/src/app/(cms)/header.tsx | 118 ++---- .../src/app/(evm)/_common/header-elements.ts | 94 +++++ apps/web/src/app/(evm)/analytics/header.tsx | 4 +- apps/web/src/app/(evm)/bonds/header.tsx | 2 + .../app/(evm)/claims/components/Header.tsx | 2 + apps/web/src/app/(evm)/pool/header.tsx | 2 + apps/web/src/app/(evm)/stake/header.tsx | 2 + apps/web/src/app/(evm)/swap/header.tsx | 2 + apps/web/src/app/(landing)/header.tsx | 120 +----- apps/web/src/app/(non-evm)/aptos/header.tsx | 2 +- apps/web/src/app/_common/header-elements.ts | 50 +++ .../ui/src/components/navigation-menu.tsx | 4 +- packages/ui/src/components/navigation.tsx | 353 ++++++------------ 14 files changed, 308 insertions(+), 451 deletions(-) create mode 100644 apps/web/src/app/(evm)/_common/header-elements.ts create mode 100644 apps/web/src/app/_common/header-elements.ts diff --git a/apps/tron/src/app/header.tsx b/apps/tron/src/app/header.tsx index 01c6426a21..0c9826752d 100644 --- a/apps/tron/src/app/header.tsx +++ b/apps/tron/src/app/header.tsx @@ -54,7 +54,7 @@ export const Navigation: FC = () => { Swap @@ -62,7 +62,7 @@ export const Navigation: FC = () => { Pool diff --git a/apps/web/src/app/(cms)/header.tsx b/apps/web/src/app/(cms)/header.tsx index 66469e80c3..5f177b4ca8 100644 --- a/apps/web/src/app/(cms)/header.tsx +++ b/apps/web/src/app/(cms)/header.tsx @@ -1,19 +1,11 @@ import { getDifficulties, getProducts } from '@sushiswap/graph-client/strapi' import { - EXPLORE_NAVIGATION_LINKS, - NavigationContainer, - NavigationListItem, - NavigationMenu, - NavigationMenuContent, - NavigationMenuItem, - NavigationMenuLink, - NavigationMenuList, - NavigationMenuTrigger, - // OnramperButton, - buttonVariants, + Navigation, + NavigationElement, + NavigationElementType, } from '@sushiswap/ui' -// import { getDifficulties, getProducts } from 'lib/api' import React from 'react' +import { EXPLORE_NAVIGATION_LINKS } from '../_common/header-elements' import { DOCS_URL } from './constants' interface HeaderLink { @@ -45,91 +37,49 @@ export async function Header() { : -1, ) - const navData: HeaderSection[] = [ - { title: 'Academy', href: '/academy' }, - { title: 'Blog', href: '/blog' }, + const navData: NavigationElement[] = [ + { + title: 'Explore', + items: EXPLORE_NAVIGATION_LINKS, + show: 'everywhere', + type: NavigationElementType.Dropdown, + }, + { + title: 'Academy', + href: '/academy', + show: 'everywhere', + type: NavigationElementType.Single, + }, + { + title: 'Blog', + href: '/blog', + show: 'everywhere', + type: NavigationElementType.Single, + }, { title: 'Products', - links: sortedProducts.map(({ longName, slug }) => ({ - name: longName, + items: sortedProducts.map(({ longName, slug }) => ({ + title: longName, href: `/academy/products/${slug}`, + description: '', })), - className: 'hidden md:flex', + show: 'desktop', + type: NavigationElementType.Dropdown, }, { title: 'Learn', - links: difficulties?.map(({ shortDescription, slug }) => { + items: difficulties?.map(({ shortDescription, slug }) => { const isTechnical = slug === 'technical' return { - name: shortDescription, + title: shortDescription, href: isTechnical ? DOCS_URL : `/academy/explore?difficulty=${slug}`, - isExternal: isTechnical, + description: '', } }), - className: 'hidden md:flex', + show: 'desktop', + type: NavigationElementType.Dropdown, }, ] - return ( - - - - - Explore - -
    - {EXPLORE_NAVIGATION_LINKS.map((component) => ( - - {component.description} - - ))} - {/* - - Need to buy some more crypto? - - */} -
-
-
- {navData.map(({ title, href, links, className }) => { - if (href && !links) { - return ( - - - {title} - - - ) - } - - return ( - - {title} - -
    - {links?.map(({ name, href }) => ( - - {name.split('-')?.[1]} - - ))} -
-
-
- ) - })} -
-
-
- ) + return } diff --git a/apps/web/src/app/(evm)/_common/header-elements.ts b/apps/web/src/app/(evm)/_common/header-elements.ts new file mode 100644 index 0000000000..ae9a05b80f --- /dev/null +++ b/apps/web/src/app/(evm)/_common/header-elements.ts @@ -0,0 +1,94 @@ +import { + type NavigationElement, + NavigationElementDropdown, + NavigationElementType, +} from '@sushiswap/ui' +import { EXPLORE_NAVIGATION_LINKS } from 'src/app/_common/header-elements' + +const TOOLS_NAVIGATION_LINKS: NavigationElementDropdown['items'] = [ + { + title: 'Analytics', + href: '/analytics', + description: 'Find the best opportunities', + }, + { + title: 'Blog', + href: '/blog', + description: + 'Stay up to date with the latest product developments at Sushi.', + }, + { + title: 'Academy', + href: '/academy', + description: 'Everything you need to get up to speed with DeFi.', + }, + { + title: 'Forum & Proposals', + href: 'https://forum.sushi.com', + description: 'View and discuss proposals for SushiSwap.', + }, + { + title: 'Participate', + href: 'https://snapshot.org/#/sushigov.eth', + description: + 'As a Sushi holder, you can vote on proposals to shape the future of SushiSwap.', + }, +] + +const PARTNER_NAVIGATION_LINKS: NavigationElementDropdown['items'] = [ + { + title: 'Partner with Sushi', + href: '/partner', + description: 'Incentivize your token with Sushi rewards.', + }, + { + title: 'List enquiry', + href: '/tokenlist-request', + description: 'Get your token on our default token list.', + }, +] + +export const headerElements: NavigationElement[] = [ + { + title: 'Explore', + items: EXPLORE_NAVIGATION_LINKS, + show: 'mobile', + type: NavigationElementType.Dropdown, + }, + { + title: 'Swap', + href: '/swap', + show: 'desktop', + type: NavigationElementType.Single, + }, + { + title: 'Pools', + href: '/pool', + show: 'desktop', + type: NavigationElementType.Single, + }, + { + title: 'Bonds', + href: '/bonds', + show: 'desktop', + type: NavigationElementType.Single, + }, + { + title: 'Stake', + href: '/stake', + show: 'desktop', + type: NavigationElementType.Single, + }, + { + title: 'More', + items: TOOLS_NAVIGATION_LINKS, + show: 'desktop', + type: NavigationElementType.Dropdown, + }, + { + title: 'Partners', + items: PARTNER_NAVIGATION_LINKS, + show: 'desktop', + type: NavigationElementType.Dropdown, + }, +] diff --git a/apps/web/src/app/(evm)/analytics/header.tsx b/apps/web/src/app/(evm)/analytics/header.tsx index f6bcd3ca85..a1b95b2955 100644 --- a/apps/web/src/app/(evm)/analytics/header.tsx +++ b/apps/web/src/app/(evm)/analytics/header.tsx @@ -3,6 +3,8 @@ import { Navigation } from '@sushiswap/ui' import React, { FC } from 'react' +import { headerElements } from '../_common/header-elements' + export const Header: FC = () => { - return + return } diff --git a/apps/web/src/app/(evm)/bonds/header.tsx b/apps/web/src/app/(evm)/bonds/header.tsx index d9062fdaeb..6ac316f610 100644 --- a/apps/web/src/app/(evm)/bonds/header.tsx +++ b/apps/web/src/app/(evm)/bonds/header.tsx @@ -4,10 +4,12 @@ import { Navigation } from '@sushiswap/ui' import React, { FC } from 'react' import { SUPPORTED_CHAIN_IDS } from 'src/config' import { WagmiHeaderComponents } from 'src/lib/wagmi/components/wagmi-header-components' +import { headerElements } from '../_common/header-elements' export const Header: FC = () => { return ( } /> ) diff --git a/apps/web/src/app/(evm)/claims/components/Header.tsx b/apps/web/src/app/(evm)/claims/components/Header.tsx index d9062fdaeb..699acc9391 100644 --- a/apps/web/src/app/(evm)/claims/components/Header.tsx +++ b/apps/web/src/app/(evm)/claims/components/Header.tsx @@ -4,10 +4,12 @@ import { Navigation } from '@sushiswap/ui' import React, { FC } from 'react' import { SUPPORTED_CHAIN_IDS } from 'src/config' import { WagmiHeaderComponents } from 'src/lib/wagmi/components/wagmi-header-components' +import { headerElements } from '../../_common/header-elements' export const Header: FC = () => { return ( } /> ) diff --git a/apps/web/src/app/(evm)/pool/header.tsx b/apps/web/src/app/(evm)/pool/header.tsx index 6c93565318..2b93fa8062 100644 --- a/apps/web/src/app/(evm)/pool/header.tsx +++ b/apps/web/src/app/(evm)/pool/header.tsx @@ -5,11 +5,13 @@ import React, { FC } from 'react' import { SUPPORTED_CHAIN_IDS } from 'src/config' import { WagmiHeaderComponents } from 'src/lib/wagmi/components/wagmi-header-components' import { useChainId } from 'wagmi' +import { headerElements } from '../_common/header-elements' export const Header: FC = () => { const chainId = useChainId() return ( } chainId={chainId} /> diff --git a/apps/web/src/app/(evm)/stake/header.tsx b/apps/web/src/app/(evm)/stake/header.tsx index d9062fdaeb..6ac316f610 100644 --- a/apps/web/src/app/(evm)/stake/header.tsx +++ b/apps/web/src/app/(evm)/stake/header.tsx @@ -4,10 +4,12 @@ import { Navigation } from '@sushiswap/ui' import React, { FC } from 'react' import { SUPPORTED_CHAIN_IDS } from 'src/config' import { WagmiHeaderComponents } from 'src/lib/wagmi/components/wagmi-header-components' +import { headerElements } from '../_common/header-elements' export const Header: FC = () => { return ( } /> ) diff --git a/apps/web/src/app/(evm)/swap/header.tsx b/apps/web/src/app/(evm)/swap/header.tsx index 6c93565318..2b93fa8062 100644 --- a/apps/web/src/app/(evm)/swap/header.tsx +++ b/apps/web/src/app/(evm)/swap/header.tsx @@ -5,11 +5,13 @@ import React, { FC } from 'react' import { SUPPORTED_CHAIN_IDS } from 'src/config' import { WagmiHeaderComponents } from 'src/lib/wagmi/components/wagmi-header-components' import { useChainId } from 'wagmi' +import { headerElements } from '../_common/header-elements' export const Header: FC = () => { const chainId = useChainId() return ( } chainId={chainId} /> diff --git a/apps/web/src/app/(landing)/header.tsx b/apps/web/src/app/(landing)/header.tsx index fefe7859bf..5423a222ab 100644 --- a/apps/web/src/app/(landing)/header.tsx +++ b/apps/web/src/app/(landing)/header.tsx @@ -1,125 +1,7 @@ 'use client' -import { - Button, - Container, - EXPLORE_NAVIGATION_LINKS, - LinkInternal, - NavigationContainer, - NavigationListItem, - NavigationMenu, - NavigationMenuContent, - NavigationMenuItem, - NavigationMenuLink, - NavigationMenuList, - NavigationMenuTrigger, - OnramperButton, - PARTNER_NAVIGATION_LINKS, - TOOLS_NAVIGATION_LINKS, - navigationMenuTriggerStyle, -} from '@sushiswap/ui' import React, { FC } from 'react' export const Header: FC = () => { - return ( - - - - - - Explore - -
    - {EXPLORE_NAVIGATION_LINKS.map((component) => ( - - {component.description} - - ))} - - - Need to buy some more crypto? - - -
-
-
- - - - Swap - - - - - - - Pools - - - - - - - Bonds - - - - - - - Stake - - - - - - - Pay - - - - - More - -
    - {TOOLS_NAVIGATION_LINKS.map((component) => ( - - {component.description} - - ))} -
-
-
- - Partners - -
    - {PARTNER_NAVIGATION_LINKS.map((component) => ( - - {component.description} - - ))} -
-
-
-
-
- - - -
-
- ) + return <> } diff --git a/apps/web/src/app/(non-evm)/aptos/header.tsx b/apps/web/src/app/(non-evm)/aptos/header.tsx index 7e3c6cb9fe..ab655b1df7 100644 --- a/apps/web/src/app/(non-evm)/aptos/header.tsx +++ b/apps/web/src/app/(non-evm)/aptos/header.tsx @@ -9,7 +9,7 @@ export const Header: FC = () => { return ( } /> ) diff --git a/apps/web/src/app/_common/header-elements.ts b/apps/web/src/app/_common/header-elements.ts new file mode 100644 index 0000000000..e3a864106a --- /dev/null +++ b/apps/web/src/app/_common/header-elements.ts @@ -0,0 +1,50 @@ +import type { NavigationElementDropdown } from '@sushiswap/ui' + +export const EXPLORE_NAVIGATION_LINKS: NavigationElementDropdown['items'] = [ + { + title: 'Swap', + href: '/swap', + description: 'The easiest way to trade.', + }, + { + title: 'Pools', + href: '/pools', + description: 'Earn fees by providing liquidity.', + }, + { + title: 'Bonds', + href: '/bonds', + description: 'Earn interest by locking up your assets.', + }, + { + title: 'Stake', + href: '/stake', + description: 'Earn protocol fees by staking SUSHI.', + }, + { + title: 'Analytics', + href: '/analytics', + description: 'Find the best opportunities', + }, + { + title: 'Blog', + href: '/blog', + description: + 'Stay up to date with the latest product developments at Sushi.', + }, + { + title: 'Academy', + href: '/academy', + description: 'Everything you need to get up to speed with DeFi.', + }, + { + title: 'Partner with Sushi', + href: '/partner', + description: 'Incentivize your token with Sushi rewards.', + }, + { + title: 'List enquiry', + href: '/tokenlist-request', + description: 'Get your token on our default token list.', + }, +] diff --git a/packages/ui/src/components/navigation-menu.tsx b/packages/ui/src/components/navigation-menu.tsx index 665704e29c..5ae73ea8fe 100644 --- a/packages/ui/src/components/navigation-menu.tsx +++ b/packages/ui/src/components/navigation-menu.tsx @@ -42,7 +42,7 @@ NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName const NavigationMenuItem = NavigationMenuPrimitive.Item -const navigationMenuTriggerStyle = () => buttonVariants({ variant: 'ghost' }) +const navigationMenuTriggerStyle = buttonVariants({ variant: 'ghost' }) const NavigationMenuTrigger = React.forwardRef< React.ElementRef, @@ -51,7 +51,7 @@ const NavigationMenuTrigger = React.forwardRef< = ({ ) } -const navigationMenuItems = [ - { - title: 'Swap', - href: '/swap', - }, - { - title: 'Pools', - href: '/pool', - }, - { - title: 'Bonds', - href: '/bonds', - }, - { - title: 'Stake', - href: '/stake', - }, - { - title: 'More', - items: TOOLS_NAVIGATION_LINKS, - }, - { - title: 'Partners', - items: PARTNER_NAVIGATION_LINKS, - }, -] as const +export type NavigationElementShow = 'mobile' | 'desktop' | 'everywhere' + +const navigationElementShowMap: Record = { + mobile: 'md:hidden block', + desktop: 'md:block hidden', + everywhere: '', +} + +export enum NavigationElementType { + Single = 'single', + Dropdown = 'dropdown', + Custom = 'custom', +} + +export type NavigationElementSingle = { + title: string + href: string + show: NavigationElementShow + type: NavigationElementType.Single +} + +export type NavigationElementDropdown = { + title: string + items: { + title: string + href: string + description: string + }[] + show: NavigationElementShow + type: NavigationElementType.Dropdown +} + +export type NavigationElementCustom = { + item: React.ReactNode + show: NavigationElementShow + type: NavigationElementType.Custom +} + +export type NavigationElement = + | NavigationElementSingle + | NavigationElementDropdown + | NavigationElementCustom interface NavProps extends VariantProps { - leftElements?: (typeof navigationMenuItems)[number]['title'][] + leftElements: NavigationElement[] rightElement?: React.ReactNode - legacyBehavior?: boolean showOnramper?: boolean chainId?: number } const Navigation: React.FC = ({ - leftElements: _leftElements = navigationMenuItems.map((entry) => entry.title), + leftElements: _leftElements, rightElement, variant, - legacyBehavior = false, }) => { const leftElements = React.useMemo(() => { - const SimpleItem = (entry: (typeof navigationMenuItems)[number]) => { - if (!('href' in entry)) { - throw new Error('Invalid entry') - } - + const SingleItem = (entry: NavigationElementSingle) => { return ( - - {legacyBehavior ? ( - - {entry.title} - - ) : ( - - {entry.title} - - )} + + + {entry.title} + ) } - const DropdownItem = (entry: (typeof navigationMenuItems)[number]) => { - if (!('items' in entry)) { - throw new Error('Invalid entry') - } - + const DropdownItem = (entry: NavigationElementDropdown) => { return ( - + {entry.title}
    @@ -236,7 +135,6 @@ const Navigation: React.FC = ({ key={component.title} title={component.title} href={component.href} - legacyBehavior={legacyBehavior} > {component.description} @@ -247,39 +145,24 @@ const Navigation: React.FC = ({ ) } - return _leftElements.map((el) => { - const entry = navigationMenuItems.find((entry) => entry.title === el)! - - if ('href' in entry) { - return SimpleItem(entry) - } else { - return DropdownItem(entry) + return _leftElements.flatMap((el) => { + switch (el.type) { + case NavigationElementType.Single: + return SingleItem(el) + case NavigationElementType.Dropdown: + return DropdownItem(el) + case NavigationElementType.Custom: + return ( +
    el.item
    + ) } }) - }, [_leftElements, legacyBehavior]) + }, [_leftElements]) return ( - - - Explore - -
      - {EXPLORE_NAVIGATION_LINKS.map((component) => ( - - {component.description} - - ))} -
    -
    -
    - {leftElements} -
    + {leftElements}
    {rightElement ? rightElement : null} @@ -288,63 +171,49 @@ const Navigation: React.FC = ({ ) } -interface NavigationListItemProps extends React.ComponentPropsWithoutRef<'a'> { - legacyBehavior?: boolean -} +interface NavigationListItemProps extends React.ComponentPropsWithoutRef<'a'> {} const NavigationListItem = React.forwardRef< React.ElementRef<'a'>, NavigationListItemProps ->( - ( - { className, title, children, legacyBehavior = false, href, ...props }, - ref, - ) => { - return ( -
  • - - {legacyBehavior || !href ? ( - -
    {title}
    -

    - {children} -

    -
    - ) : ( - -
    {title}
    -

    - {children} -

    - - )} -
    -
  • - ) - }, -) +>(({ className, title, children, href, ...props }, ref) => { + return ( +
  • + + {!href ? ( + +
    {title}
    +

    + {children} +

    +
    + ) : ( + +
    {title}
    +

    + {children} +

    + + )} +
    +
  • + ) +}) NavigationListItem.displayName = 'NavListItem' -export { - EXPLORE_NAVIGATION_LINKS, - Navigation, - NavigationContainer, - NavigationListItem, - PARTNER_NAVIGATION_LINKS, - TOOLS_NAVIGATION_LINKS, -} +export { Navigation, NavigationContainer, NavigationListItem } From 778ce88ca7a4e014fd3c1ea11fdf94597abe0696 Mon Sep 17 00:00:00 2001 From: LufyCZ Date: Sat, 3 Aug 2024 12:31:50 +0000 Subject: [PATCH 023/125] feat(apps/web): add header where it's missing --- apps/web/src/app/(non-evm)/aptos/header.tsx | 24 +++++++++++++++++--- apps/web/src/app/partner/layout.tsx | 16 +++++++++++++ apps/web/src/app/privacy-policy/layout.tsx | 9 +++++++- apps/web/src/app/terms-of-service/layout.tsx | 9 +++++++- packages/ui/src/components/navigation.tsx | 1 - 5 files changed, 53 insertions(+), 6 deletions(-) create mode 100644 apps/web/src/app/partner/layout.tsx diff --git a/apps/web/src/app/(non-evm)/aptos/header.tsx b/apps/web/src/app/(non-evm)/aptos/header.tsx index ab655b1df7..292d709b65 100644 --- a/apps/web/src/app/(non-evm)/aptos/header.tsx +++ b/apps/web/src/app/(non-evm)/aptos/header.tsx @@ -1,15 +1,33 @@ 'use client' -import { Navigation } from '@sushiswap/ui' +import { + Navigation, + NavigationElement, + NavigationElementType, +} from '@sushiswap/ui' import React, { FC } from 'react' import { UserProfile } from './(common)/ui/user-profile/user-profile' +const nagivationElements: NavigationElement[] = [ + { + title: 'Swap', + href: '/aptos/swap', + show: 'everywhere', + type: NavigationElementType.Single, + }, + { + title: 'Pool', + href: '/aptos/pool', + show: 'everywhere', + type: NavigationElementType.Single, + }, +] + export const Header: FC = () => { return ( } /> ) diff --git a/apps/web/src/app/partner/layout.tsx b/apps/web/src/app/partner/layout.tsx new file mode 100644 index 0000000000..b7b5bddcd3 --- /dev/null +++ b/apps/web/src/app/partner/layout.tsx @@ -0,0 +1,16 @@ +import { Navigation } from '@sushiswap/ui' +import { Metadata } from 'next' +import { headerElements } from '../(evm)/_common/header-elements' + +export const metadata: Metadata = { + title: 'Partner', +} + +export default function Layout({ children }: { children: React.ReactNode }) { + return ( + <> + +
    {children}
    + + ) +} diff --git a/apps/web/src/app/privacy-policy/layout.tsx b/apps/web/src/app/privacy-policy/layout.tsx index 59eeae3e28..774cc651ee 100644 --- a/apps/web/src/app/privacy-policy/layout.tsx +++ b/apps/web/src/app/privacy-policy/layout.tsx @@ -1,9 +1,16 @@ +import { Navigation } from '@sushiswap/ui' import { Metadata } from 'next' +import { headerElements } from '../(evm)/_common/header-elements' export const metadata: Metadata = { title: 'Privacy Policy', } export default function Layout({ children }: { children: React.ReactNode }) { - return
    {children}
    + return ( + <> + +
    {children}
    + + ) } diff --git a/apps/web/src/app/terms-of-service/layout.tsx b/apps/web/src/app/terms-of-service/layout.tsx index a90584e6a3..ecf29a4e4d 100644 --- a/apps/web/src/app/terms-of-service/layout.tsx +++ b/apps/web/src/app/terms-of-service/layout.tsx @@ -1,9 +1,16 @@ +import { Navigation } from '@sushiswap/ui' import { Metadata } from 'next' +import { headerElements } from '../(evm)/_common/header-elements' export const metadata: Metadata = { title: 'Terms Of Service', } export default function Layout({ children }: { children: React.ReactNode }) { - return
    {children}
    + return ( + <> + +
    {children}
    + + ) } diff --git a/packages/ui/src/components/navigation.tsx b/packages/ui/src/components/navigation.tsx index e102a98c1d..4ec91e5edc 100644 --- a/packages/ui/src/components/navigation.tsx +++ b/packages/ui/src/components/navigation.tsx @@ -95,7 +95,6 @@ export type NavigationElement = interface NavProps extends VariantProps { leftElements: NavigationElement[] rightElement?: React.ReactNode - showOnramper?: boolean chainId?: number } From 7227d50d044083b70cfe47158028f66a1661e4bf Mon Sep 17 00:00:00 2001 From: LufyCZ Date: Sat, 3 Aug 2024 12:43:41 +0000 Subject: [PATCH 024/125] fix(apps/aptos): links --- apps/web/next.config.mjs | 5 +++++ .../(common)/lib/edge/use-is-swap-maintenance.ts | 2 +- .../app/(non-evm)/aptos/pool/(landing)/layout.tsx | 15 ++++++++++----- apps/web/src/app/(non-evm)/aptos/pool/hero.tsx | 2 +- .../pool/ui/pools/tables/pools/PoolsTable.tsx | 2 +- .../tables/positions/pool-positions-table.tsx | 2 +- 6 files changed, 19 insertions(+), 9 deletions(-) diff --git a/apps/web/next.config.mjs b/apps/web/next.config.mjs index deaebdc6b5..17ae1114ca 100644 --- a/apps/web/next.config.mjs +++ b/apps/web/next.config.mjs @@ -63,6 +63,11 @@ const nextConfig = bundleAnalyzer({ permanent: true, destination: '/pool/:path*', }, + { + source: '/aptos', + permanent: true, + destination: '/aptos/swap', + }, { source: '/skale/swap', permanent: true, diff --git a/apps/web/src/app/(non-evm)/aptos/(common)/lib/edge/use-is-swap-maintenance.ts b/apps/web/src/app/(non-evm)/aptos/(common)/lib/edge/use-is-swap-maintenance.ts index 2146774b2c..6fca6d3f20 100644 --- a/apps/web/src/app/(non-evm)/aptos/(common)/lib/edge/use-is-swap-maintenance.ts +++ b/apps/web/src/app/(non-evm)/aptos/(common)/lib/edge/use-is-swap-maintenance.ts @@ -8,7 +8,7 @@ export const useIsSwapMaintenance = () => { return useQuery({ queryKey: ['useIsSwapMaintenance'], queryFn: async () => { - const resp = await fetch('/api/config/swap', { + const resp = await fetch('/aptos/api/config/swap', { next: { revalidate: 60 }, }) const data = await resp.json() diff --git a/apps/web/src/app/(non-evm)/aptos/pool/(landing)/layout.tsx b/apps/web/src/app/(non-evm)/aptos/pool/(landing)/layout.tsx index 93d02cb0e0..f3293409a3 100644 --- a/apps/web/src/app/(non-evm)/aptos/pool/(landing)/layout.tsx +++ b/apps/web/src/app/(non-evm)/aptos/pool/(landing)/layout.tsx @@ -22,20 +22,25 @@ export default function TabsLayout({ - + All Pools @@ -50,7 +55,7 @@ export default function TabsLayout({ My Rewards diff --git a/apps/web/src/app/(non-evm)/aptos/pool/hero.tsx b/apps/web/src/app/(non-evm)/aptos/pool/hero.tsx index 1901dd8a2c..5acef8fe01 100644 --- a/apps/web/src/app/(non-evm)/aptos/pool/hero.tsx +++ b/apps/web/src/app/(non-evm)/aptos/pool/hero.tsx @@ -32,7 +32,7 @@ export const Hero: FC = () => {
    diff --git a/apps/web/src/app/(non-evm)/aptos/pool/ui/pools/tables/pools/PoolsTable.tsx b/apps/web/src/app/(non-evm)/aptos/pool/ui/pools/tables/pools/PoolsTable.tsx index 7a49c13e58..0b9c8201b2 100644 --- a/apps/web/src/app/(non-evm)/aptos/pool/ui/pools/tables/pools/PoolsTable.tsx +++ b/apps/web/src/app/(non-evm)/aptos/pool/ui/pools/tables/pools/PoolsTable.tsx @@ -44,7 +44,7 @@ export const PoolsTable = () => { // } = useNetwork() const rowLink = useCallback((row: PoolExtended) => { - return `/pool/${row.id}` + return `/aptos/pool/${row.id}` }, []) const filtered = useMemo(() => { diff --git a/apps/web/src/app/(non-evm)/aptos/pool/ui/pools/tables/positions/pool-positions-table.tsx b/apps/web/src/app/(non-evm)/aptos/pool/ui/pools/tables/positions/pool-positions-table.tsx index 03c0c3cedb..f89eb5c5fd 100644 --- a/apps/web/src/app/(non-evm)/aptos/pool/ui/pools/tables/positions/pool-positions-table.tsx +++ b/apps/web/src/app/(non-evm)/aptos/pool/ui/pools/tables/positions/pool-positions-table.tsx @@ -61,7 +61,7 @@ export const PositionsTable = () => { }, [pools, tokenSymbols]) const rowLink = useCallback((row: PoolExtended) => { - return `/pool/${row.id}` + return `/aptos/pool/${row.id}` }, []) const state: Partial = useMemo(() => { From 5199677b6a4d1d7a95d7a3f6bad114d5afb1628c Mon Sep 17 00:00:00 2001 From: 0xMasayoshi <0xMasayoshi@protonmail.com> Date: Sat, 3 Aug 2024 20:45:46 +0700 Subject: [PATCH 025/125] fix: network icon classnames --- packages/ui/src/icons/network/circle/EthereumCircle.tsx | 3 ++- packages/ui/src/icons/network/circle/GnosisCircle.tsx | 3 ++- packages/ui/src/icons/network/circle/TelosCircle.tsx | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/ui/src/icons/network/circle/EthereumCircle.tsx b/packages/ui/src/icons/network/circle/EthereumCircle.tsx index 18debd3522..7dafcf3817 100644 --- a/packages/ui/src/icons/network/circle/EthereumCircle.tsx +++ b/packages/ui/src/icons/network/circle/EthereumCircle.tsx @@ -2,12 +2,13 @@ import * as React from 'react' import { EthereumNaked } from '../naked/EthereumNaked' +import classNames from 'classnames' import { IconComponent } from '../../../types' export const EthereumCircle: IconComponent = (props) => ( } /> ) diff --git a/packages/ui/src/icons/network/circle/GnosisCircle.tsx b/packages/ui/src/icons/network/circle/GnosisCircle.tsx index 886a9a5e8d..096493a6fe 100644 --- a/packages/ui/src/icons/network/circle/GnosisCircle.tsx +++ b/packages/ui/src/icons/network/circle/GnosisCircle.tsx @@ -2,12 +2,13 @@ import * as React from 'react' import { GnosisNaked } from '../naked/GnosisNaked' +import classNames from 'classnames' import { IconComponent } from '../../../types' export const GnosisCircle: IconComponent = (props) => ( } /> ) diff --git a/packages/ui/src/icons/network/circle/TelosCircle.tsx b/packages/ui/src/icons/network/circle/TelosCircle.tsx index 37acb5a082..03025b297a 100644 --- a/packages/ui/src/icons/network/circle/TelosCircle.tsx +++ b/packages/ui/src/icons/network/circle/TelosCircle.tsx @@ -2,12 +2,13 @@ import * as React from 'react' import { TelosNaked } from '../naked/TelosNaked' +import classNames from 'classnames' import { IconComponent } from '../../../types' export const TelosCircle: IconComponent = (props) => ( } /> ) From dd8e24db44aeaef162a13db1154410b021defb7a Mon Sep 17 00:00:00 2001 From: 0xMasayoshi <0xMasayoshi@protonmail.com> Date: Sat, 3 Aug 2024 22:32:44 +0700 Subject: [PATCH 026/125] feat: v3 fees dashboard --- apps/web/src/app/(evm)/pool/fees/layout.tsx | 13 ++ apps/web/src/app/(evm)/pool/fees/page.tsx | 195 ++++++++++++++++++ apps/web/src/lib/hooks/api/index.ts | 1 + .../src/lib/hooks/api/useV3PoolsWithFees.ts | 33 +++ .../src/subgraphs/sushi-v3/index.ts | 1 + .../sushi-v3/queries/pools-with-fees.ts | 56 +++++ 6 files changed, 299 insertions(+) create mode 100644 apps/web/src/app/(evm)/pool/fees/layout.tsx create mode 100644 apps/web/src/app/(evm)/pool/fees/page.tsx create mode 100644 apps/web/src/lib/hooks/api/useV3PoolsWithFees.ts create mode 100644 packages/graph-client/src/subgraphs/sushi-v3/queries/pools-with-fees.ts diff --git a/apps/web/src/app/(evm)/pool/fees/layout.tsx b/apps/web/src/app/(evm)/pool/fees/layout.tsx new file mode 100644 index 0000000000..b48a8ebbf2 --- /dev/null +++ b/apps/web/src/app/(evm)/pool/fees/layout.tsx @@ -0,0 +1,13 @@ +import { Container } from '@sushiswap/ui' + +export default function Layout({ children }: { children: React.ReactNode }) { + return ( +
    +
    + + {children} + +
    +
    + ) +} diff --git a/apps/web/src/app/(evm)/pool/fees/page.tsx b/apps/web/src/app/(evm)/pool/fees/page.tsx new file mode 100644 index 0000000000..639a42f5aa --- /dev/null +++ b/apps/web/src/app/(evm)/pool/fees/page.tsx @@ -0,0 +1,195 @@ +'use client' + +import { + Badge, + Card, + Container, + Currency, + DataTable, + SkeletonCircle, + SkeletonText, + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, + classNames, +} from '@sushiswap/ui' +import { NetworkIcon } from '@sushiswap/ui/icons/NetworkIcon' +import { ColumnDef, SortingState, TableState } from '@tanstack/react-table' +import { useMemo, useState } from 'react' +import { V3PoolsWithFees, useV3PoolsWithFees } from 'src/lib/hooks' +import { ProtocolBadge } from 'src/ui/pool/PoolNameCell' +import { Chain, ChainId } from 'sushi' +import { isSushiSwapV3ChainId } from 'sushi/config' +import { formatNumber, formatUSD } from 'sushi/format' +import { useChainId } from 'wagmi' + +const NAME_COLUMN_POOL: ColumnDef = { + id: 'name', + header: 'Name', + + cell: (props) => ( +
    +
    + + } + > + + + + + +
    +
    + + {props.row.original.token0.symbol}{' '} + + / + {' '} + {props.row.original.token1.symbol}{' '} +
    + +
    + + + + {ProtocolBadge['SUSHISWAP_V3']} + + +

    Protocol version

    +
    +
    +
    + + + +
    + {formatNumber(props.row.original.swapFee * 100)}% +
    +
    + +

    Swap fee

    +
    +
    +
    +
    +
    +
    + ), + meta: { + skeleton: ( +
    +
    + + +
    +
    + +
    +
    + ), + }, + size: 300, +} + +const TVL_COLUMN: ColumnDef = { + id: 'liquidityUSD', + header: 'TVL', + accessorFn: (row) => row.liquidityUSD, + sortingFn: ({ original: rowA }, { original: rowB }) => + rowA.liquidityUSD - rowB.liquidityUSD, + cell: (props) => + formatUSD(props.row.original.liquidityUSD).includes('NaN') + ? '$0.00' + : formatUSD(props.row.original.liquidityUSD), + meta: { + skeleton: , + }, +} + +const VOLUME_COLUMN: ColumnDef = { + id: 'volumeUSD', + header: 'Volume', + accessorFn: (row) => row.volumeUSD, + sortingFn: ({ original: rowA }, { original: rowB }) => + rowA.volumeUSD - rowB.volumeUSD, + cell: (props) => + formatUSD(props.row.original.volumeUSD).includes('NaN') + ? '$0.00' + : formatUSD(props.row.original.volumeUSD), + meta: { + skeleton: , + }, +} + +const PROTOCOL_FEE_COLUMN: ColumnDef = { + id: 'isProtocolFeeEnabled', + header: 'Fee Enabled', + accessorFn: (row) => row.volumeUSD, + sortingFn: ({ original: rowA }, { original: rowB }) => + +rowA.isProtocolFeeEnabled - +rowB.isProtocolFeeEnabled, + cell: (props) => (props.row.original.isProtocolFeeEnabled ? '✅' : '❌'), + meta: { + skeleton: , + }, +} + +const COLUMNS = [ + NAME_COLUMN_POOL, + TVL_COLUMN, + VOLUME_COLUMN, + PROTOCOL_FEE_COLUMN, +] + +export default function Page() { + const chainId = useChainId() + + const { data: pools, isLoading } = useV3PoolsWithFees({ + chainId: isSushiSwapV3ChainId(chainId) ? chainId : ChainId.ETHEREUM, + }) + + const [sorting, setSorting] = useState([ + { id: 'liquidityUSD', desc: true }, + ]) + + const data = useMemo(() => pools?.flat() || [], [pools]) + + const state: Partial = useMemo(() => { + return { + sorting, + pagination: { + pageIndex: 0, + pageSize: data.length, + }, + } + }, [data.length, sorting]) + + return ( + + + + Chain.from(chainId).getAccountUrl(row.address) + } + /> + + + ) +} diff --git a/apps/web/src/lib/hooks/api/index.ts b/apps/web/src/lib/hooks/api/index.ts index 2e23bf3293..c1d0b781b7 100644 --- a/apps/web/src/lib/hooks/api/index.ts +++ b/apps/web/src/lib/hooks/api/index.ts @@ -3,3 +3,4 @@ export * from './useGraphPool' export * from './usePoolGraphData' export * from './useSkaleEuropaFaucet' export * from './useSushiV2UserPositions' +export * from './useV3PoolsWithFees' diff --git a/apps/web/src/lib/hooks/api/useV3PoolsWithFees.ts b/apps/web/src/lib/hooks/api/useV3PoolsWithFees.ts new file mode 100644 index 0000000000..5c6f9968bb --- /dev/null +++ b/apps/web/src/lib/hooks/api/useV3PoolsWithFees.ts @@ -0,0 +1,33 @@ +'use client' + +import { + GetSushiV3PoolsWithFees, + SushiV3PoolsWithFees, + getSushiV3PoolsWithFees, +} from '@sushiswap/graph-client/sushi-v3' +import { UseQueryOptions, useQuery } from '@tanstack/react-query' +import { Token } from 'sushi/currency' + +export type V3PoolsWithFees = Array< + Omit & { + token0: Token + token1: Token + } +> + +export const useV3PoolsWithFees = ( + params: GetSushiV3PoolsWithFees, + options?: Omit, 'queryFn' | 'queryKey'>, +) => + useQuery({ + queryKey: [params], + queryFn: async () => { + const pools = await getSushiV3PoolsWithFees(params) + return pools.map((pool) => ({ + ...pool, + token0: new Token(pool.token0), + token1: new Token(pool.token1), + })) + }, + ...options, + }) diff --git a/packages/graph-client/src/subgraphs/sushi-v3/index.ts b/packages/graph-client/src/subgraphs/sushi-v3/index.ts index 01ca79084e..8d62e4fd6d 100644 --- a/packages/graph-client/src/subgraphs/sushi-v3/index.ts +++ b/packages/graph-client/src/subgraphs/sushi-v3/index.ts @@ -7,5 +7,6 @@ export * from './queries/pool-with-buckets' export * from './queries/pool' export * from './queries/pools' export * from './queries/pools-by-token-pair' +export * from './queries/pools-with-fees' export * from './queries/swaps' export * from './queries/transactions' diff --git a/packages/graph-client/src/subgraphs/sushi-v3/queries/pools-with-fees.ts b/packages/graph-client/src/subgraphs/sushi-v3/queries/pools-with-fees.ts new file mode 100644 index 0000000000..3162339f91 --- /dev/null +++ b/packages/graph-client/src/subgraphs/sushi-v3/queries/pools-with-fees.ts @@ -0,0 +1,56 @@ +import type { VariablesOf } from 'gql.tada' +import type { SushiSwapV3ChainId } from 'sushi/config' +import { SUSHISWAP_V3_SUBGRAPH_URL } from 'sushi/config/subgraph' + +import { FetchError } from 'src/lib/fetch-error' +import type { RequestOptions } from 'src/lib/request' +import { requestPaged } from 'src/lib/request-paged' +import type { ChainIdVariable } from 'src/lib/types/chainId' +import { transformPoolV3ToBase } from 'src/subgraphs/sushi-v3/transforms/pool-v3-to-base' +import { PoolFieldsFragment } from '../fragments/pool-fields' +import { graphql } from '../graphql' + +export const SushiV3PoolsWithFeesQuery = graphql( + ` + query Pools($first: Int = 1000, $skip: Int = 0, $block: Block_height, $orderBy: Pool_orderBy, $orderDirection: OrderDirection, $where: Pool_filter) { + pools(first: $first, skip: $skip, block: $block, orderBy: $orderBy, orderDirection: $orderDirection, where: $where) { + ...PoolFields, + isProtocolFeeEnabled + } + } +`, + [PoolFieldsFragment], +) + +export type GetSushiV3PoolsWithFees = VariablesOf< + typeof SushiV3PoolsWithFeesQuery +> & + ChainIdVariable + +export async function getSushiV3PoolsWithFees( + { chainId, ...variables }: GetSushiV3PoolsWithFees, + options?: RequestOptions, +) { + const url = `https://${SUSHISWAP_V3_SUBGRAPH_URL[chainId]}` + + const result = await requestPaged({ + chainId, + url, + query: SushiV3PoolsWithFeesQuery, + variables, + options, + }) + + if (result) { + return result.pools.map((pool) => ({ + ...transformPoolV3ToBase(pool, chainId), + isProtocolFeeEnabled: pool.isProtocolFeeEnabled, + })) + } + + throw new FetchError(chainId, 'Failed to fetch pools') +} + +export type SushiV3PoolsWithFees = Awaited< + ReturnType +> From 83fdf95eaf19696271eb35e6a6b9ce881e24b18e Mon Sep 17 00:00:00 2001 From: 0xMasayoshi <0xMasayoshi@protonmail.com> Date: Sun, 4 Aug 2024 14:12:18 +0700 Subject: [PATCH 027/125] feat: add enable button --- apps/web/src/app/(evm)/pool/fees/page.tsx | 57 +++++++++++++++++++++-- 1 file changed, 52 insertions(+), 5 deletions(-) diff --git a/apps/web/src/app/(evm)/pool/fees/page.tsx b/apps/web/src/app/(evm)/pool/fees/page.tsx index 639a42f5aa..0a7fccc4c5 100644 --- a/apps/web/src/app/(evm)/pool/fees/page.tsx +++ b/apps/web/src/app/(evm)/pool/fees/page.tsx @@ -2,6 +2,7 @@ import { Badge, + Button, Card, Container, Currency, @@ -16,13 +17,18 @@ import { } from '@sushiswap/ui' import { NetworkIcon } from '@sushiswap/ui/icons/NetworkIcon' import { ColumnDef, SortingState, TableState } from '@tanstack/react-table' -import { useMemo, useState } from 'react' +import { FC, MouseEventHandler, useCallback, useMemo, useState } from 'react' import { V3PoolsWithFees, useV3PoolsWithFees } from 'src/lib/hooks' import { ProtocolBadge } from 'src/ui/pool/PoolNameCell' -import { Chain, ChainId } from 'sushi' +import { Address, Chain, ChainId } from 'sushi' +import { uniswapV3PoolAbi } from 'sushi/abi' import { isSushiSwapV3ChainId } from 'sushi/config' import { formatNumber, formatUSD } from 'sushi/format' -import { useChainId } from 'wagmi' +import { + useChainId, + useWaitForTransactionReceipt, + useWriteContract, +} from 'wagmi' const NAME_COLUMN_POOL: ColumnDef = { id: 'name', @@ -134,13 +140,54 @@ const VOLUME_COLUMN: ColumnDef = { }, } +const EnableProtocolFeeButton: FC<{ pool: Address }> = ({ pool }) => { + const { data: txHash, writeContract, isPending } = useWriteContract() + const { isLoading, isSuccess } = useWaitForTransactionReceipt({ + hash: txHash, + }) + + const onClick: MouseEventHandler = useCallback( + (e) => { + e.preventDefault() + writeContract({ + address: pool, + abi: uniswapV3PoolAbi, + functionName: 'setFeeProtocol', + args: [4, 4], + }) + }, + [writeContract, pool], + ) + + return isSuccess ? ( + '✅' + ) : ( + + ) +} + const PROTOCOL_FEE_COLUMN: ColumnDef = { id: 'isProtocolFeeEnabled', - header: 'Fee Enabled', + header: () => 'Fees Enabled', accessorFn: (row) => row.volumeUSD, sortingFn: ({ original: rowA }, { original: rowB }) => +rowA.isProtocolFeeEnabled - +rowB.isProtocolFeeEnabled, - cell: (props) => (props.row.original.isProtocolFeeEnabled ? '✅' : '❌'), + cell: (props) => ( +
    + {props.row.original.isProtocolFeeEnabled ? ( + '✅' + ) : ( + + )} +
    + ), meta: { skeleton: , }, From e3c3e7c193c58ea0ab9a568657e14afabb20c17e Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Sun, 4 Aug 2024 10:45:04 +0100 Subject: [PATCH 028/125] chore: use v5 api in regular swap --- apis/router/src/handlers/swap2/schema.ts | 2 +- .../src/lib/swap/cross-chain/actions/getTrade.ts | 4 +--- packages/react-query/src/hooks/trade/useTrade.ts | 16 ++++++++++++++-- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/apis/router/src/handlers/swap2/schema.ts b/apis/router/src/handlers/swap2/schema.ts index cb01631ee6..ff6e3518d5 100644 --- a/apis/router/src/handlers/swap2/schema.ts +++ b/apis/router/src/handlers/swap2/schema.ts @@ -46,7 +46,7 @@ export const querySchema5 = z.object({ .default(0.005), // includeRoute: z.boolean().default(true), // includeTx: z.boolean().default(true), - enableFee: z.boolean().default(true), + enableFee: z.coerce.boolean().default(true), feeReceiver: z.custom
    ( (val) => isAddressFast(val), (val) => ({ message: `Incorrect fee receiver address: ${val}` }), diff --git a/apps/web/src/lib/swap/cross-chain/actions/getTrade.ts b/apps/web/src/lib/swap/cross-chain/actions/getTrade.ts index 5cc8008358..bdd2a2eb52 100644 --- a/apps/web/src/lib/swap/cross-chain/actions/getTrade.ts +++ b/apps/web/src/lib/swap/cross-chain/actions/getTrade.ts @@ -38,9 +38,7 @@ export const getTrade = async ({ recipient, source, }: GetTrade) => { - const params = new URL( - `${TRADE_API_BASE_URL}/swap${getTradeQueryApiVersion(chainId)}/${chainId}`, - ) + const params = new URL(`${TRADE_API_BASE_URL}/swap/v4/${chainId}`) params.searchParams.set('chainId', `${chainId}`) params.searchParams.set('tokenIn', `${fromToken}`) params.searchParams.set('tokenOut', `${toToken}`) diff --git a/packages/react-query/src/hooks/trade/useTrade.ts b/packages/react-query/src/hooks/trade/useTrade.ts index ae5b5bb762..242756c11c 100644 --- a/packages/react-query/src/hooks/trade/useTrade.ts +++ b/packages/react-query/src/hooks/trade/useTrade.ts @@ -7,7 +7,11 @@ import { useQuery } from '@tanstack/react-query' import { useCallback, useMemo } from 'react' import { slippageAmount } from 'sushi/calculate' import { ChainId } from 'sushi/chain' -import { isRouteProcessor4ChainId, isWNativeSupported } from 'sushi/config' +import { + isRouteProcessor4ChainId, + isRouteProcessor5ChainId, + isWNativeSupported, +} from 'sushi/config' import { Amount, Native, Price, type Type } from 'sushi/currency' import { Fraction, Percent, ZERO } from 'sushi/math' import { type Address, type Hex, stringify, zeroAddress } from 'viem' @@ -26,7 +30,9 @@ export const TRADE_API_BASE_URL = 'https://api.sushi.com/swap' export function getTradeQueryApiVersion(chainId: ChainId) { - if (isRouteProcessor4ChainId(chainId)) { + if (isRouteProcessor5ChainId(chainId)) { + return '/v5' + } else if (isRouteProcessor4ChainId(chainId)) { return '/v4' } return '' @@ -89,6 +95,12 @@ export const useTradeQuery = ( params.searchParams.set('gasPrice', `${gasPrice}`) params.searchParams.set('to', `${recipient}`) params.searchParams.set('preferSushi', 'true') + params.searchParams.set('enableFee', 'true') + // params.searchParams.set( + // 'feeReceiver', + // '0x8f54C8c2df62c94772ac14CcFc85603742976312', + // ) + // params.searchParams.set('feeAmount', '0.0025') if (source !== undefined) params.searchParams.set('source', `${source}`) const res = await fetch(params.toString()) From fbb01bdd12c28fbf09fe351a05e0931d8ea7c79c Mon Sep 17 00:00:00 2001 From: 0xMasayoshi <0xMasayoshi@protonmail.com> Date: Sun, 4 Aug 2024 17:33:00 +0700 Subject: [PATCH 029/125] fix: column header --- apps/web/src/app/(evm)/pool/fees/page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web/src/app/(evm)/pool/fees/page.tsx b/apps/web/src/app/(evm)/pool/fees/page.tsx index 0a7fccc4c5..d68a7da174 100644 --- a/apps/web/src/app/(evm)/pool/fees/page.tsx +++ b/apps/web/src/app/(evm)/pool/fees/page.tsx @@ -175,7 +175,7 @@ const EnableProtocolFeeButton: FC<{ pool: Address }> = ({ pool }) => { const PROTOCOL_FEE_COLUMN: ColumnDef = { id: 'isProtocolFeeEnabled', - header: () => 'Fees Enabled', + header: 'Fees Enabled', accessorFn: (row) => row.volumeUSD, sortingFn: ({ original: rowA }, { original: rowB }) => +rowA.isProtocolFeeEnabled - +rowB.isProtocolFeeEnabled, From 3b8fdd1ebbab9ac37d1e6af3d82b50c959b102f3 Mon Sep 17 00:00:00 2001 From: 0xMasayoshi <0xMasayoshi@protonmail.com> Date: Sun, 4 Aug 2024 17:56:22 +0700 Subject: [PATCH 030/125] fix: useV3PoolsWithFees params --- apps/web/src/app/(evm)/pool/fees/page.tsx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/apps/web/src/app/(evm)/pool/fees/page.tsx b/apps/web/src/app/(evm)/pool/fees/page.tsx index d68a7da174..0388a6d4ef 100644 --- a/apps/web/src/app/(evm)/pool/fees/page.tsx +++ b/apps/web/src/app/(evm)/pool/fees/page.tsx @@ -22,7 +22,7 @@ import { V3PoolsWithFees, useV3PoolsWithFees } from 'src/lib/hooks' import { ProtocolBadge } from 'src/ui/pool/PoolNameCell' import { Address, Chain, ChainId } from 'sushi' import { uniswapV3PoolAbi } from 'sushi/abi' -import { isSushiSwapV3ChainId } from 'sushi/config' +import { SushiSwapV3ChainId, isSushiSwapV3ChainId } from 'sushi/config' import { formatNumber, formatUSD } from 'sushi/format' import { useChainId, @@ -203,9 +203,12 @@ const COLUMNS = [ export default function Page() { const chainId = useChainId() - const { data: pools, isLoading } = useV3PoolsWithFees({ - chainId: isSushiSwapV3ChainId(chainId) ? chainId : ChainId.ETHEREUM, - }) + const { data: pools, isLoading } = useV3PoolsWithFees( + { + chainId: chainId as SushiSwapV3ChainId, + }, + { enabled: isSushiSwapV3ChainId(chainId), staleTime: Infinity }, + ) const [sorting, setSorting] = useState([ { id: 'liquidityUSD', desc: true }, From e8aebae3b2494ef0415719bdbef8ec918261b399 Mon Sep 17 00:00:00 2001 From: 0xMasayoshi <0xMasayoshi@protonmail.com> Date: Sun, 4 Aug 2024 17:57:11 +0700 Subject: [PATCH 031/125] chore: update v3 subgraph endpoints --- .../sushi/src/config/subgraph/subgraphs/sushiswap-v3.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/sushi/src/config/subgraph/subgraphs/sushiswap-v3.ts b/packages/sushi/src/config/subgraph/subgraphs/sushiswap-v3.ts index 010e03a5f9..b357f3bd5a 100644 --- a/packages/sushi/src/config/subgraph/subgraphs/sushiswap-v3.ts +++ b/packages/sushi/src/config/subgraph/subgraphs/sushiswap-v3.ts @@ -29,13 +29,13 @@ export const SUSHISWAP_V3_SUBGRAPH_URL: Record = { [ChainId.LINEA]: `${DECENTRALIZED_HOST_BY_DEPLOYMENT_ID}/QmNZ9ePvxGRDHAEhb7cLsb3AvtCCPJ3qAwh1CDvDn39RMa`, [ChainId.SCROLL]: `${DECENTRALIZED_HOST_BY_DEPLOYMENT_ID}/QmR6VP1qoF8nxhtMaGEg9VMmkaTDFqyeM8nJWkakP6nHes`, [ChainId.ARBITRUM_NOVA]: `${SUSHI_DEDICATED_GOLDSKY_HOST}/sushi-v3/v3-arbitrum-nova/gn`, - [ChainId.THUNDERCORE]: `${THUNDERCORE_HOST}/sushi-v3/v3-thundercore`, - [ChainId.CORE]: `${CORE_HOST}/sushi-v3/v3-core-fix`, + [ChainId.THUNDERCORE]: `${THUNDERCORE_HOST}/sushi-v3/v3-thundercore-2`, + [ChainId.CORE]: `${CORE_HOST}/sushi-v3/v3-core-tvl-fix`, [ChainId.KAVA]: `${SUSHI_DEDICATED_GOLDSKY_HOST}/sushi-v3/v3-kava/gn`, [ChainId.METIS]: `${METIS_0XGRAPH_HOST}/sushiswap/v3-metis`, [ChainId.BTTC]: `${SUSHI_DEDICATED_GOLDSKY_HOST}/sushi-v3/v3-bttc/gn`, [ChainId.FILECOIN]: `${FILECOIN_HOST}/sushiswap/v3-filecoin`, - [ChainId.HAQQ]: `${HAQQ_HOST}/sushi/v3-haqq`, + [ChainId.HAQQ]: `${HAQQ_HOST}/sushi/v3-haqq-2`, [ChainId.ZETACHAIN]: `${SUSHI_GOLDSKY_HOST}/v3-zetachain/1.0.0/gn`, [ChainId.BLAST]: `${SUSHI_DEDICATED_GOLDSKY_HOST}/sushiswap/v3-blast/gn`, [ChainId.SKALE_EUROPA]: `${SKALE_HOST}/sushi/v3-skale-europa`, From aac8e20407725961d3c2b4f5c38b04f946200d88 Mon Sep 17 00:00:00 2001 From: 0xMasayoshi <0xMasayoshi@protonmail.com> Date: Sun, 4 Aug 2024 17:57:11 +0700 Subject: [PATCH 032/125] chore: update v3 subgraph endpoints --- .../sushi/src/config/subgraph/subgraphs/sushiswap-v3.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/sushi/src/config/subgraph/subgraphs/sushiswap-v3.ts b/packages/sushi/src/config/subgraph/subgraphs/sushiswap-v3.ts index 010e03a5f9..b357f3bd5a 100644 --- a/packages/sushi/src/config/subgraph/subgraphs/sushiswap-v3.ts +++ b/packages/sushi/src/config/subgraph/subgraphs/sushiswap-v3.ts @@ -29,13 +29,13 @@ export const SUSHISWAP_V3_SUBGRAPH_URL: Record = { [ChainId.LINEA]: `${DECENTRALIZED_HOST_BY_DEPLOYMENT_ID}/QmNZ9ePvxGRDHAEhb7cLsb3AvtCCPJ3qAwh1CDvDn39RMa`, [ChainId.SCROLL]: `${DECENTRALIZED_HOST_BY_DEPLOYMENT_ID}/QmR6VP1qoF8nxhtMaGEg9VMmkaTDFqyeM8nJWkakP6nHes`, [ChainId.ARBITRUM_NOVA]: `${SUSHI_DEDICATED_GOLDSKY_HOST}/sushi-v3/v3-arbitrum-nova/gn`, - [ChainId.THUNDERCORE]: `${THUNDERCORE_HOST}/sushi-v3/v3-thundercore`, - [ChainId.CORE]: `${CORE_HOST}/sushi-v3/v3-core-fix`, + [ChainId.THUNDERCORE]: `${THUNDERCORE_HOST}/sushi-v3/v3-thundercore-2`, + [ChainId.CORE]: `${CORE_HOST}/sushi-v3/v3-core-tvl-fix`, [ChainId.KAVA]: `${SUSHI_DEDICATED_GOLDSKY_HOST}/sushi-v3/v3-kava/gn`, [ChainId.METIS]: `${METIS_0XGRAPH_HOST}/sushiswap/v3-metis`, [ChainId.BTTC]: `${SUSHI_DEDICATED_GOLDSKY_HOST}/sushi-v3/v3-bttc/gn`, [ChainId.FILECOIN]: `${FILECOIN_HOST}/sushiswap/v3-filecoin`, - [ChainId.HAQQ]: `${HAQQ_HOST}/sushi/v3-haqq`, + [ChainId.HAQQ]: `${HAQQ_HOST}/sushi/v3-haqq-2`, [ChainId.ZETACHAIN]: `${SUSHI_GOLDSKY_HOST}/v3-zetachain/1.0.0/gn`, [ChainId.BLAST]: `${SUSHI_DEDICATED_GOLDSKY_HOST}/sushiswap/v3-blast/gn`, [ChainId.SKALE_EUROPA]: `${SKALE_HOST}/sushi/v3-skale-europa`, From 663b3372d9e81b43e4febc742091255b97541e3a Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Sun, 4 Aug 2024 17:00:46 +0100 Subject: [PATCH 033/125] feat: charge fee by input or output support --- apis/router/src/handlers/swap2/index.ts | 49 +++++++++++++--- apis/router/src/handlers/swap2/schema.ts | 24 +++++--- .../react-query/src/hooks/trade/useTrade.ts | 3 +- packages/sushi/src/config/stables.ts | 7 +++ packages/sushi/src/currency/native.ts | 1 + packages/sushi/src/currency/token.ts | 1 + packages/sushi/src/router/router.ts | 58 ++++++++++++++----- 7 files changed, 111 insertions(+), 32 deletions(-) diff --git a/apis/router/src/handlers/swap2/index.ts b/apis/router/src/handlers/swap2/index.ts index 1c28d5ff84..a4d0c32484 100644 --- a/apis/router/src/handlers/swap2/index.ts +++ b/apis/router/src/handlers/swap2/index.ts @@ -9,9 +9,12 @@ import { ProcessFunction, Router, RouterLiquiditySource, + TransferValue, + isUnwrap, + isWrap, makeAPI02Object, } from 'sushi/router' -import { MultiRoute } from 'sushi/tines' +import { MultiRoute, getBigInt } from 'sushi/tines' import { Address } from 'viem' import { z } from 'zod' import { ExtractorClient } from '../../ExtractorClient.js' @@ -55,6 +58,9 @@ const handler = ( let poolCodesMap: Map = new Map() let bestRoute: MultiRoute | undefined = undefined + let amountValueTransfer: bigint | undefined = undefined + let processFunction = ProcessFunction.ProcessRoute + const statistics = swapRequestStatistics.requestProcessingStart() const parsed = querySchema.safeParse(req.query) if (!parsed.success) { @@ -69,7 +75,7 @@ const handler = ( const { tokenIn: _tokenIn, tokenOut: _tokenOut, - amount, + amount: _amount, gasPrice, source, to, @@ -79,6 +85,7 @@ const handler = ( enableFee, feeReceiver, feeAmount, + chargeFeeBy, } = parsed.data if ( client.lastUpdatedTimestamp + MAX_TIME_WITHOUT_NETWORK_UPDATE < @@ -116,11 +123,30 @@ const handler = ( ) } + const isWrapOrUnwap = + isWrap({ fromToken: tokenIn, toToken: tokenOut }) || + isUnwrap({ fromToken: tokenIn, toToken: tokenOut }) + poolCodesMap = client.getKnownPoolsForTokens(tokenIn, tokenOut) nativeProvider .getCurrentPoolList() .forEach((p) => poolCodesMap.set(p.pool.uniqueID(), p)) + const chargeFee = !isWrapOrUnwap && enableFee + + const chargeFeeByInput = chargeFeeBy === TransferValue.Input + + if (chargeFee && chargeFeeByInput) { + processFunction = ProcessFunction.ProcessRouteWithTransferValueInput + amountValueTransfer = + (_amount * getBigInt(feeAmount * 1_000_000)) / 1_000_000n + } + + const amount = + chargeFeeByInput && amountValueTransfer + ? _amount - amountValueTransfer + : _amount + bestRoute = preferSushi ? Router.findSpecialRoute( poolCodesMap, @@ -146,6 +172,17 @@ const handler = ( ) bestRoute = Router.NoWayMultiRoute(tokenIn, tokenOut) + const minAmountOut = + (bestRoute.amountOutBI * getBigInt((1 - maxSlippage) * 1_000_000)) / + 1_000_000n + + if (chargeFee && !chargeFeeByInput) { + processFunction = ProcessFunction.ProcessRouteWithTransferValueOutput + + amountValueTransfer = + (minAmountOut * getBigInt(feeAmount * 1_000_000)) / 1_000_000n + } + const rpParams = to ? routeProcessorParams( poolCodesMap, @@ -155,13 +192,11 @@ const handler = ( to, routeProcessorAddress, [], - maxSlippage, + maxSlippage, // probably just pass min amount out through instead? source ?? RouterLiquiditySource.Sender, - enableFee - ? ProcessFunction.ProcessRouteWithTransferValueOutput - : ProcessFunction.ProcessRoute, + processFunction, feeReceiver, - feeAmount, + amountValueTransfer, ) : undefined diff --git a/apis/router/src/handlers/swap2/schema.ts b/apis/router/src/handlers/swap2/schema.ts index ff6e3518d5..8705a38cda 100644 --- a/apis/router/src/handlers/swap2/schema.ts +++ b/apis/router/src/handlers/swap2/schema.ts @@ -1,4 +1,4 @@ -import { RouterLiquiditySource } from 'sushi/router' +import { RouterLiquiditySource, TransferValue } from 'sushi/router' import { isAddressFast } from 'sushi/serializer' import type { Address } from 'viem' import z from 'zod' @@ -47,15 +47,23 @@ export const querySchema5 = z.object({ // includeRoute: z.boolean().default(true), // includeTx: z.boolean().default(true), enableFee: z.coerce.boolean().default(true), - feeReceiver: z.custom
    ( - (val) => isAddressFast(val), - (val) => ({ message: `Incorrect fee receiver address: ${val}` }), + feeReceiver: z.optional( + z.custom
    ( + (val) => isAddressFast(val), + (val) => ({ message: `Incorrect fee receiver address: ${val}` }), + ), ), - feeAmount: z.coerce - .number() - .lte(0.003, 'feeAmount should be less than or equal to 0.003') - .positive() + feeAmount: z + .optional( + z.coerce + .number() + .lte(0.003, 'feeAmount should be less than or equal to 0.003') + .positive(), + ) .default(0.0025), + chargeFeeBy: z + .optional(z.nativeEnum(TransferValue)) + .default(TransferValue.Output), }) export type querySchema5 = z.infer diff --git a/packages/react-query/src/hooks/trade/useTrade.ts b/packages/react-query/src/hooks/trade/useTrade.ts index a4f6cd0bd2..da17ce0f16 100644 --- a/packages/react-query/src/hooks/trade/useTrade.ts +++ b/packages/react-query/src/hooks/trade/useTrade.ts @@ -98,9 +98,10 @@ export const useTradeQuery = ( params.searchParams.set('enableFee', 'true') params.searchParams.set( 'feeReceiver', - '0x8f54C8c2df62c94772ac14CcFc85603742976312', + '0x32464Be3D71ed9105c142FB6bdEe98a0c649cdd3', ) params.searchParams.set('feeAmount', '0.0025') + params.searchParams.set('chargeFeeBy', 'output') if (source !== undefined) params.searchParams.set('source', `${source}`) const res = await fetch(params.toString()) diff --git a/packages/sushi/src/config/stables.ts b/packages/sushi/src/config/stables.ts index 086c613fb5..9b1d5f8b57 100644 --- a/packages/sushi/src/config/stables.ts +++ b/packages/sushi/src/config/stables.ts @@ -215,6 +215,8 @@ export const STABLES = { USDP[ChainId.SKALE_EUROPA], ], [ChainId.ROOTSTOCK]: [USDT[ChainId.ROOTSTOCK], DAI[ChainId.ROOTSTOCK]], + [ChainId.PALM]: [], + [ChainId.ZKSYNC_ERA]: [], // TESTNETS // [ChainId.RINKEBY]: [USDC[ChainId.RINKEBY]], // [ChainId.ROPSTEN]: [ @@ -228,4 +230,9 @@ export const STABLES = { // DAI[ChainId.KOVAN], // ], [ChainId.POLYGON_TESTNET]: [USDC[ChainId.POLYGON_TESTNET]], + [ChainId.FANTOM_TESTNET]: [], + [ChainId.BSC_TESTNET]: [], + [ChainId.ARBITRUM_TESTNET]: [], + [ChainId.AVALANCHE_TESTNET]: [], + [ChainId.SEPOLIA]: [], } as const diff --git a/packages/sushi/src/currency/native.ts b/packages/sushi/src/currency/native.ts index 2f2285d54c..ce848e7fdd 100644 --- a/packages/sushi/src/currency/native.ts +++ b/packages/sushi/src/currency/native.ts @@ -8,6 +8,7 @@ import { type SerializedNative, nativeSchema } from './zod.js' export class Native extends Currency { public readonly id: string + // public readonly address = '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE' public readonly isNative = true as const public readonly isToken = false as const public override readonly symbol: string diff --git a/packages/sushi/src/currency/token.ts b/packages/sushi/src/currency/token.ts index c90fbc8c83..3eda664fdd 100644 --- a/packages/sushi/src/currency/token.ts +++ b/packages/sushi/src/currency/token.ts @@ -10,6 +10,7 @@ export class Token extends Currency { public readonly id: string public readonly isNative = false as const public readonly isToken = true as const + /** * The contract address on the chain on which this token lives */ diff --git a/packages/sushi/src/router/router.ts b/packages/sushi/src/router/router.ts index 7b02b5cbdc..4c5b61a0a4 100644 --- a/packages/sushi/src/router/router.ts +++ b/packages/sushi/src/router/router.ts @@ -35,6 +35,11 @@ import { import { getRouteProcessor4Code } from './tines-to-route-processor-4.js' import { getRouteProcessorCode } from './tines-to-route-processor.js' +export enum TransferValue { + Input = 'input', + Output = 'output', +} + export enum ProcessFunction { ProcessRoute = 0, TransferValueAndprocessRoute = 1, @@ -85,13 +90,24 @@ const RP5processRouteEncodeData = [ }), ] -const isWrap = ({ fromToken, toToken }: { fromToken: Type; toToken: Type }) => +export const isWrap = ({ + fromToken, + toToken, +}: { fromToken: Type; toToken: Type }) => fromToken.isNative && toToken.wrapped.address === Native.onChain(toToken.chainId).wrapped.address -const isUnwrap = ({ fromToken, toToken }: { fromToken: Type; toToken: Type }) => +export const isUnwrap = ({ + fromToken, + toToken, +}: { fromToken: Type; toToken: Type }) => toToken.isNative && fromToken.wrapped.address === Native.onChain(fromToken.chainId).wrapped.address +export const isWrapOrUnwrap = ({ + fromToken, + toToken, +}: { fromToken: Type; toToken: Type }) => + isWrap({ fromToken, toToken }) || isUnwrap({ fromToken, toToken }) export interface RPParams { tokenIn: Address @@ -413,8 +429,7 @@ export class Router { source = RouterLiquiditySource.Sender, processFunction = ProcessFunction.ProcessRoute, transferValueTo?: Address, - feeAmount?: number, - // amountValueTransfer?: bigint, + amountValueTransfer?: bigint, ): RPParams { const tokenIn = fromToken instanceof Token @@ -431,17 +446,18 @@ export class Router { : (route.amountOutBI * getBigInt((1 - maxSlippage) * 1_000_000)) / 1_000_000n - const routeCode = getRouteProcessor4Code( - route, - RPAddr, - to, - poolCodesMap, - permits, - source, - ) as Hex + let routeCode: Hex let data: Hex - if (isWrapOrUnwap || processFunction === ProcessFunction.ProcessRoute) { + if (processFunction === ProcessFunction.ProcessRoute) { + routeCode = getRouteProcessor4Code( + route, + RPAddr, + to, + poolCodesMap, + permits, + source, + ) as Hex data = encodeFunctionData({ ...RP5processRouteEncodeData[processFunction], args: [ @@ -454,9 +470,19 @@ export class Router { ], }) } else { - const amountValueTransfer = - (route.amountOutBI * getBigInt((1 - feeAmount!) * 1_000_000)) / - 1_000_000n + if (!transferValueTo || !amountValueTransfer) { + throw new Error('Missing transferValueTo or feeAmount') + } + routeCode = getRouteProcessor4Code( + route, + RPAddr, + processFunction === ProcessFunction.ProcessRouteWithTransferValueInput + ? to + : RPAddr, + poolCodesMap, + permits, + source, + ) as Hex data = encodeFunctionData({ ...RP5processRouteEncodeData[processFunction], args: [ From b5dd526c4e5bff5ede4a4c2da4a15c4cfd0b2d2a Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Sun, 4 Aug 2024 17:07:02 +0100 Subject: [PATCH 034/125] fix: fees to multisig address --- apis/router/src/handlers/swap2/index.ts | 1 - packages/react-query/src/hooks/trade/useTrade.ts | 6 +++++- packages/sushi/src/config/index.ts | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/apis/router/src/handlers/swap2/index.ts b/apis/router/src/handlers/swap2/index.ts index a4d0c32484..57efc5112a 100644 --- a/apis/router/src/handlers/swap2/index.ts +++ b/apis/router/src/handlers/swap2/index.ts @@ -1,4 +1,3 @@ -import { Logger, safeSerialize } from '@sushiswap/extractor' import { Request, Response } from 'express' import { ChainId } from 'sushi/chain' import { ROUTE_PROCESSOR_5_ADDRESS } from 'sushi/config' diff --git a/packages/react-query/src/hooks/trade/useTrade.ts b/packages/react-query/src/hooks/trade/useTrade.ts index da17ce0f16..c0027b1538 100644 --- a/packages/react-query/src/hooks/trade/useTrade.ts +++ b/packages/react-query/src/hooks/trade/useTrade.ts @@ -8,6 +8,8 @@ import { useCallback, useMemo } from 'react' import { slippageAmount } from 'sushi/calculate' import { ChainId } from 'sushi/chain' import { + MULTISIG_ADDRESS, + isMultisigChainId, isRouteProcessor4ChainId, isRouteProcessor5ChainId, isWNativeSupported, @@ -98,7 +100,9 @@ export const useTradeQuery = ( params.searchParams.set('enableFee', 'true') params.searchParams.set( 'feeReceiver', - '0x32464Be3D71ed9105c142FB6bdEe98a0c649cdd3', + isMultisigChainId(chainId) + ? MULTISIG_ADDRESS[chainId] + : '0xFF64C2d5e23e9c48e8b42a23dc70055EEC9ea098', ) params.searchParams.set('feeAmount', '0.0025') params.searchParams.set('chargeFeeBy', 'output') diff --git a/packages/sushi/src/config/index.ts b/packages/sushi/src/config/index.ts index 506948bf01..5a779fb49f 100644 --- a/packages/sushi/src/config/index.ts +++ b/packages/sushi/src/config/index.ts @@ -26,3 +26,4 @@ export * from './uniswap-v2.js' export * from './uniswap-v3.js' export * from './viem.js' export * from './wnative.js' +export * from './wallet.js' From b89b86825dcf3c8fc95ecc14c5c863a7ca52d191 Mon Sep 17 00:00:00 2001 From: 0xMasayoshi <0xMasayoshi@protonmail.com> Date: Mon, 5 Aug 2024 13:38:29 +0700 Subject: [PATCH 035/125] chore: update metis subgraph --- apps/web/src/app/(evm)/pool/fees/page.tsx | 2 +- packages/sushi/src/config/subgraph/hosts.ts | 3 ++- packages/sushi/src/config/subgraph/subgraphs/sushiswap-v3.ts | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/web/src/app/(evm)/pool/fees/page.tsx b/apps/web/src/app/(evm)/pool/fees/page.tsx index 0388a6d4ef..e7ebd2d553 100644 --- a/apps/web/src/app/(evm)/pool/fees/page.tsx +++ b/apps/web/src/app/(evm)/pool/fees/page.tsx @@ -20,7 +20,7 @@ import { ColumnDef, SortingState, TableState } from '@tanstack/react-table' import { FC, MouseEventHandler, useCallback, useMemo, useState } from 'react' import { V3PoolsWithFees, useV3PoolsWithFees } from 'src/lib/hooks' import { ProtocolBadge } from 'src/ui/pool/PoolNameCell' -import { Address, Chain, ChainId } from 'sushi' +import { Address, Chain } from 'sushi' import { uniswapV3PoolAbi } from 'sushi/abi' import { SushiSwapV3ChainId, isSushiSwapV3ChainId } from 'sushi/config' import { formatNumber, formatUSD } from 'sushi/format' diff --git a/packages/sushi/src/config/subgraph/hosts.ts b/packages/sushi/src/config/subgraph/hosts.ts index 5ce4587f2a..a308bc5dee 100644 --- a/packages/sushi/src/config/subgraph/hosts.ts +++ b/packages/sushi/src/config/subgraph/hosts.ts @@ -21,7 +21,8 @@ export const GOLDSKY_COMMUNITY_HOST = 'api.goldsky.com/api/public/project_cl8ylkiw00krx0hvza0qw17vn/subgraphs' export const WAGMI_METIS_HOST = 'metis.graph.wagmi.com/subgraphs/name' export const WAGMI_KAVA_HOST = 'kava.graph.wagmi.com/subgraphs/name' -export const METIS_0XGRAPH_HOST = 'metisapi.0xgraph.xyz/subgraphs/name' +export const METIS_0XGRAPH_HOST = + 'metisapi.0xgraph.xyz/api/public/fc1ae952-7a36-44ac-9e9b-f46d70cedf7d/subgraphs' export const SKALE_HOST = 'elated-tan-skat-graph.skalenodes.com:8000/subgraphs/name' diff --git a/packages/sushi/src/config/subgraph/subgraphs/sushiswap-v3.ts b/packages/sushi/src/config/subgraph/subgraphs/sushiswap-v3.ts index b357f3bd5a..25ede50235 100644 --- a/packages/sushi/src/config/subgraph/subgraphs/sushiswap-v3.ts +++ b/packages/sushi/src/config/subgraph/subgraphs/sushiswap-v3.ts @@ -32,7 +32,7 @@ export const SUSHISWAP_V3_SUBGRAPH_URL: Record = { [ChainId.THUNDERCORE]: `${THUNDERCORE_HOST}/sushi-v3/v3-thundercore-2`, [ChainId.CORE]: `${CORE_HOST}/sushi-v3/v3-core-tvl-fix`, [ChainId.KAVA]: `${SUSHI_DEDICATED_GOLDSKY_HOST}/sushi-v3/v3-kava/gn`, - [ChainId.METIS]: `${METIS_0XGRAPH_HOST}/sushiswap/v3-metis`, + [ChainId.METIS]: `${METIS_0XGRAPH_HOST}/sushi-v3/v3-metis/v0.0.1/gn`, [ChainId.BTTC]: `${SUSHI_DEDICATED_GOLDSKY_HOST}/sushi-v3/v3-bttc/gn`, [ChainId.FILECOIN]: `${FILECOIN_HOST}/sushiswap/v3-filecoin`, [ChainId.HAQQ]: `${HAQQ_HOST}/sushi/v3-haqq-2`, From 3c213ce3fae750c435111fbd2ee0a5c8d2228c31 Mon Sep 17 00:00:00 2001 From: 0xMasayoshi <0xMasayoshi@protonmail.com> Date: Mon, 5 Aug 2024 13:38:29 +0700 Subject: [PATCH 036/125] chore: update metis v3 subgraph --- packages/sushi/src/config/subgraph/hosts.ts | 3 ++- packages/sushi/src/config/subgraph/subgraphs/sushiswap-v3.ts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/sushi/src/config/subgraph/hosts.ts b/packages/sushi/src/config/subgraph/hosts.ts index 5ce4587f2a..a308bc5dee 100644 --- a/packages/sushi/src/config/subgraph/hosts.ts +++ b/packages/sushi/src/config/subgraph/hosts.ts @@ -21,7 +21,8 @@ export const GOLDSKY_COMMUNITY_HOST = 'api.goldsky.com/api/public/project_cl8ylkiw00krx0hvza0qw17vn/subgraphs' export const WAGMI_METIS_HOST = 'metis.graph.wagmi.com/subgraphs/name' export const WAGMI_KAVA_HOST = 'kava.graph.wagmi.com/subgraphs/name' -export const METIS_0XGRAPH_HOST = 'metisapi.0xgraph.xyz/subgraphs/name' +export const METIS_0XGRAPH_HOST = + 'metisapi.0xgraph.xyz/api/public/fc1ae952-7a36-44ac-9e9b-f46d70cedf7d/subgraphs' export const SKALE_HOST = 'elated-tan-skat-graph.skalenodes.com:8000/subgraphs/name' diff --git a/packages/sushi/src/config/subgraph/subgraphs/sushiswap-v3.ts b/packages/sushi/src/config/subgraph/subgraphs/sushiswap-v3.ts index b357f3bd5a..25ede50235 100644 --- a/packages/sushi/src/config/subgraph/subgraphs/sushiswap-v3.ts +++ b/packages/sushi/src/config/subgraph/subgraphs/sushiswap-v3.ts @@ -32,7 +32,7 @@ export const SUSHISWAP_V3_SUBGRAPH_URL: Record = { [ChainId.THUNDERCORE]: `${THUNDERCORE_HOST}/sushi-v3/v3-thundercore-2`, [ChainId.CORE]: `${CORE_HOST}/sushi-v3/v3-core-tvl-fix`, [ChainId.KAVA]: `${SUSHI_DEDICATED_GOLDSKY_HOST}/sushi-v3/v3-kava/gn`, - [ChainId.METIS]: `${METIS_0XGRAPH_HOST}/sushiswap/v3-metis`, + [ChainId.METIS]: `${METIS_0XGRAPH_HOST}/sushi-v3/v3-metis/v0.0.1/gn`, [ChainId.BTTC]: `${SUSHI_DEDICATED_GOLDSKY_HOST}/sushi-v3/v3-bttc/gn`, [ChainId.FILECOIN]: `${FILECOIN_HOST}/sushiswap/v3-filecoin`, [ChainId.HAQQ]: `${HAQQ_HOST}/sushi/v3-haqq-2`, From 249722882e7c6701715a20d5531820eea4043912 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Mon, 5 Aug 2024 19:09:58 +0100 Subject: [PATCH 037/125] chore: lint --- apps/web/src/lib/swap/cross-chain/actions/getTrade.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web/src/lib/swap/cross-chain/actions/getTrade.ts b/apps/web/src/lib/swap/cross-chain/actions/getTrade.ts index bdd2a2eb52..930aabcd27 100644 --- a/apps/web/src/lib/swap/cross-chain/actions/getTrade.ts +++ b/apps/web/src/lib/swap/cross-chain/actions/getTrade.ts @@ -1,7 +1,7 @@ import { TRADE_API_BASE_URL, UseTradeParams, - getTradeQueryApiVersion, + // getTradeQueryApiVersion, tradeValidator02, } from '@sushiswap/react-query' import { RouteStatus } from 'sushi/tines' From 0ed60f1cf2472908a25a498df04ab5221741375f Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Tue, 6 Aug 2024 02:43:02 +0100 Subject: [PATCH 038/125] chore: remove ts-ignore --- apis/router/src/ExtractorClient.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/apis/router/src/ExtractorClient.ts b/apis/router/src/ExtractorClient.ts index 64ecae9b2f..84dacb7bd1 100644 --- a/apis/router/src/ExtractorClient.ts +++ b/apis/router/src/ExtractorClient.ts @@ -347,8 +347,7 @@ export class ExtractorClient { for (let i = 0; i < tokens.length; ++i) { for (let j = i + 1; j < tokens.length; ++j) { const pairPools = this.poolCodesMap.get( - // @ts-ignore - tokenPairId(tokens[i], tokens[j]), + tokenPairId(tokens[i]!, tokens[j]!), ) if (pairPools !== undefined) pairPools.forEach((p) => pools.set(p.pool.uniqueID(), p)) @@ -405,8 +404,7 @@ export class ExtractorClient { const tokensUnique: Type[] = [] tokensSorted.forEach((t) => { if (tokensUnique.length === 0) tokensUnique.push(t) - // @ts-ignore - else if (tokenId(tokensUnique[tokensUnique.length - 1]) !== tokenId(t)) + else if (tokenId(tokensUnique[tokensUnique.length - 1]!) !== tokenId(t)) tokensUnique.push(t) }) From 5b869a439bd1215fc46a3436aaeaeed3fcba11a3 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Tue, 6 Aug 2024 02:43:23 +0100 Subject: [PATCH 039/125] chore: add curve config for ethereum --- apis/extractor/src/config.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apis/extractor/src/config.ts b/apis/extractor/src/config.ts index f368f61c27..fe3ca8af83 100644 --- a/apis/extractor/src/config.ts +++ b/apis/extractor/src/config.ts @@ -338,6 +338,9 @@ export const EXTRACTOR_CONFIG: Record< sushiswapV3Factory(ChainId.ETHEREUM), pancakeswapV3Factory(ChainId.ETHEREUM), ], + curveConfig: { + minPoolLiquidityLimitUSD: 1000, + }, tickHelperContractV3: SUSHISWAP_V3_TICK_LENS[ChainId.ETHEREUM], tickHelperContractAlgebra: '0x0000000000000000000000000000000000000000' as Address, From f7aaec8da1bb80378a81ad95fb735275ca9455e2 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Tue, 6 Aug 2024 02:44:56 +0100 Subject: [PATCH 040/125] chore: use max slippage and add fee to trade return --- .../react-query/src/hooks/trade/useTrade.ts | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/packages/react-query/src/hooks/trade/useTrade.ts b/packages/react-query/src/hooks/trade/useTrade.ts index c0027b1538..381548fa98 100644 --- a/packages/react-query/src/hooks/trade/useTrade.ts +++ b/packages/react-query/src/hooks/trade/useTrade.ts @@ -93,7 +93,7 @@ export const useTradeQuery = ( }`, ) params.searchParams.set('amount', `${amount?.quotient.toString()}`) - params.searchParams.set('maxPriceImpact', `${+slippagePercentage / 100}`) + params.searchParams.set('maxSlippage', `${+slippagePercentage / 100}`) params.searchParams.set('gasPrice', `${gasPrice}`) params.searchParams.set('to', `${recipient}`) params.searchParams.set('preferSushi', 'true') @@ -154,6 +154,16 @@ export const useTrade = (variables: UseTradeParams) => { enabled: isWNativeSupported(chainId), }) + // const { data: tokenInPrice } = usePrice({ + // chainId, + // address: fromToken?.wrapped.address, + // }) + + const { data: tokenOutPrice } = usePrice({ + chainId, + address: toToken?.wrapped.address, + }) + const price = useMemo(() => { return Native.onChain(chainId).wrapped.address === zeroAddress ? new Fraction(0) @@ -227,6 +237,12 @@ export const useTrade = (variables: UseTradeParams) => { price && gasSpent ? gasSpent.multiply(price.asFraction).toSignificant(4) : undefined, + fee: tokenOutPrice + ? minAmountOut + .multiply(new Percent(25, 10000)) + .multiply(tokenOutPrice.asFraction) + .toSignificant(4) + : undefined, route: data.route, functionName: isOffset ? 'transferValueAndprocessRoute' @@ -246,6 +262,7 @@ export const useTrade = (variables: UseTradeParams) => { minAmountOut: undefined, gasSpent: undefined, gasSpentUsd: undefined, + fee: undefined, writeArgs: undefined, route: undefined, functionName: 'processRoute', @@ -260,6 +277,7 @@ export const useTrade = (variables: UseTradeParams) => { chainId, fromToken, price, + tokenInPrice, slippagePercentage, toToken, gasPrice, From 279c37bf86bab116a5384a644d58059810a953de Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Tue, 6 Aug 2024 02:45:26 +0100 Subject: [PATCH 041/125] chore: display usd fee in swap trade stats --- .../swap/simple/simple-swap-trade-stats.tsx | 26 +++++++++++-------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/apps/web/src/ui/swap/simple/simple-swap-trade-stats.tsx b/apps/web/src/ui/swap/simple/simple-swap-trade-stats.tsx index 8bf04857e9..18f6372757 100644 --- a/apps/web/src/ui/swap/simple/simple-swap-trade-stats.tsx +++ b/apps/web/src/ui/swap/simple/simple-swap-trade-stats.tsx @@ -90,16 +90,18 @@ export const SimpleSwapTradeStats: FC = () => {
    - {trade?.tokenTax ? ( -
    - - Token tax - - - {trade.tokenTax.toPercentageString()} - -
    - ) : null} +
    + + Fee (0.25%) + + + {loading || !trade?.fee ? ( + + ) : ( + `$${trade?.fee}` + )} + +
    @@ -111,7 +113,9 @@ export const SimpleSwapTradeStats: FC = () => { ) : loading || !trade?.gasSpent || trade.gasSpent === '0' ? ( ) : trade?.gasSpent ? ( - `${trade.gasSpent} ${Native.onChain(chainId).symbol}` + `${trade.gasSpent} ${Native.onChain(chainId).symbol} ($${ + trade.gasSpentUsd + })` ) : null}
    From b8ac80856c6c5bcd1583cf699ed360ee12a29d4a Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Tue, 6 Aug 2024 02:45:46 +0100 Subject: [PATCH 042/125] chore: add fee to trade return type --- packages/react-query/src/hooks/trade/types.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-query/src/hooks/trade/types.ts b/packages/react-query/src/hooks/trade/types.ts index d8e3bcac0e..e17ee1b7d7 100644 --- a/packages/react-query/src/hooks/trade/types.ts +++ b/packages/react-query/src/hooks/trade/types.ts @@ -45,6 +45,7 @@ export interface UseTradeReturn { value?: bigint | undefined tokenTax: Percent | false | undefined txdata: string | undefined + fee: string | undefined } export type UseTradeQuerySelect = (data: TradeType) => UseTradeReturn From 1fc6be4120be6fc3a742f2bffb1474394c59144d Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Tue, 6 Aug 2024 02:46:09 +0100 Subject: [PATCH 043/125] feat: add is stable function to router --- packages/sushi/src/router/router.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/packages/sushi/src/router/router.ts b/packages/sushi/src/router/router.ts index 4c5b61a0a4..bc537b1b09 100644 --- a/packages/sushi/src/router/router.ts +++ b/packages/sushi/src/router/router.ts @@ -11,6 +11,7 @@ import { routeProcessorAbi } from '../abi/routeProcessorAbi.js' import { ChainId } from '../chain/index.js' import { ADDITIONAL_BASES } from '../config/additional-bases.js' import { BASES_TO_CHECK_TRADES_AGAINST } from '../config/bases-to-check-trades-against.js' +import { STABLES } from '../config/stables.js' import { Native, WNATIVE, WNATIVE_ADDRESS } from '../currency/index.js' import { Token, type Type } from '../currency/index.js' import { @@ -109,6 +110,19 @@ export const isWrapOrUnwrap = ({ }: { fromToken: Type; toToken: Type }) => isWrap({ fromToken, toToken }) || isUnwrap({ fromToken, toToken }) +export const isStable = ({ + fromToken, + toToken, +}: { fromToken: Type; toToken: Type }) => { + const fromTokenIsStable = STABLES[fromToken.chainId].some( + (t: Token) => t === fromToken.wrapped, + ) + const toTokenIsStable = STABLES[toToken.chainId].some( + (t: Token) => t === toToken.wrapped, + ) + return fromTokenIsStable && toTokenIsStable +} + export interface RPParams { tokenIn: Address amountIn: bigint From 9211608d8250e55d210b264a8aeb5fb4ec3fe3ad Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Tue, 6 Aug 2024 02:47:04 +0100 Subject: [PATCH 044/125] feat: disable chage fee if is stable and return no way multiroute is price impact undefined --- apis/router/src/handlers/swap2/index.ts | 33 +++++++++++++++--------- apis/router/src/handlers/swap2/schema.ts | 1 + 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/apis/router/src/handlers/swap2/index.ts b/apis/router/src/handlers/swap2/index.ts index 57efc5112a..b2e73710ce 100644 --- a/apis/router/src/handlers/swap2/index.ts +++ b/apis/router/src/handlers/swap2/index.ts @@ -1,3 +1,4 @@ +import { Logger, safeSerialize } from '@sushiswap/extractor' import { Request, Response } from 'express' import { ChainId } from 'sushi/chain' import { ROUTE_PROCESSOR_5_ADDRESS } from 'sushi/config' @@ -9,6 +10,7 @@ import { Router, RouterLiquiditySource, TransferValue, + isStable, isUnwrap, isWrap, makeAPI02Object, @@ -25,6 +27,7 @@ import { MAX_TIME_WITHOUT_NETWORK_UPDATE, POOL_FETCH_TIMEOUT, } from '../../config.js' +// import { swapResponse } from './response.js' import { querySchema5 } from './schema.js' const nativeProvider = new NativeWrapProvider( @@ -122,27 +125,27 @@ const handler = ( ) } - const isWrapOrUnwap = - isWrap({ fromToken: tokenIn, toToken: tokenOut }) || - isUnwrap({ fromToken: tokenIn, toToken: tokenOut }) - poolCodesMap = client.getKnownPoolsForTokens(tokenIn, tokenOut) nativeProvider .getCurrentPoolList() .forEach((p) => poolCodesMap.set(p.pool.uniqueID(), p)) - const chargeFee = !isWrapOrUnwap && enableFee - - const chargeFeeByInput = chargeFeeBy === TransferValue.Input + const chargeFee = + enableFee && + !( + isWrap({ fromToken: tokenIn, toToken: tokenOut }) || + isUnwrap({ fromToken: tokenIn, toToken: tokenOut }) + ) && + !isStable({ fromToken: tokenIn, toToken: tokenOut }) - if (chargeFee && chargeFeeByInput) { + if (chargeFee && chargeFeeBy === TransferValue.Input) { processFunction = ProcessFunction.ProcessRouteWithTransferValueInput amountValueTransfer = (_amount * getBigInt(feeAmount * 1_000_000)) / 1_000_000n } const amount = - chargeFeeByInput && amountValueTransfer + chargeFeeBy === TransferValue.Input && amountValueTransfer ? _amount - amountValueTransfer : _amount @@ -166,8 +169,11 @@ const handler = ( ) if ( - maxPriceImpact !== undefined && - (bestRoute.priceImpact ?? 0) > maxPriceImpact + // If price impact is missing from the route we return no way multiroute + bestRoute.priceImpact === undefined || + (maxPriceImpact !== undefined && + // or if max price impact is defined and less than best route price impact we return no way multiroute (not a feature we use at UI) + bestRoute.priceImpact > maxPriceImpact) ) bestRoute = Router.NoWayMultiRoute(tokenIn, tokenOut) @@ -175,7 +181,7 @@ const handler = ( (bestRoute.amountOutBI * getBigInt((1 - maxSlippage) * 1_000_000)) / 1_000_000n - if (chargeFee && !chargeFeeByInput) { + if (chargeFee && chargeFeeBy === TransferValue.Output) { processFunction = ProcessFunction.ProcessRouteWithTransferValueOutput amountValueTransfer = @@ -201,6 +207,8 @@ const handler = ( const json = makeAPI02Object(bestRoute, rpParams, routeProcessorAddress) + // return swapResponse() + swapRequestStatistics.requestWasProcessed(statistics, tokensAreKnown) return res.json(json) } catch (e) { @@ -222,6 +230,7 @@ const handler = ( if (parsed.data) data.params = parsed.data if (bestRoute) data.route = makeAPI02Object(bestRoute, undefined, '') } catch (_e) {} + Logger.error(CHAIN_ID, 'Routing crashed', safeSerialize(data), false) return res.status(500).send('Internal server error: Routing crashed') diff --git a/apis/router/src/handlers/swap2/schema.ts b/apis/router/src/handlers/swap2/schema.ts index 8705a38cda..70dfc2381a 100644 --- a/apis/router/src/handlers/swap2/schema.ts +++ b/apis/router/src/handlers/swap2/schema.ts @@ -45,6 +45,7 @@ export const querySchema5 = z.object({ .positive() .default(0.005), // includeRoute: z.boolean().default(true), + // includeRpArgs: z.boolean().default(true), // includeTx: z.boolean().default(true), enableFee: z.coerce.boolean().default(true), feeReceiver: z.optional( From b0c3be0eb4463beb87f5eb1b6ed10c7f5e3de176 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Tue, 6 Aug 2024 02:47:51 +0100 Subject: [PATCH 045/125] chore: lock --- apis/router/src/handlers/swap2/response.ts | 2 + k8s/chart/values.yaml | 128 ++++++++++----------- packages/sushi/src/types/api.ts | 1 + pnpm-lock.yaml | 4 + 4 files changed, 71 insertions(+), 64 deletions(-) create mode 100644 apis/router/src/handlers/swap2/response.ts create mode 100644 packages/sushi/src/types/api.ts diff --git a/apis/router/src/handlers/swap2/response.ts b/apis/router/src/handlers/swap2/response.ts new file mode 100644 index 0000000000..d178fe53a1 --- /dev/null +++ b/apis/router/src/handlers/swap2/response.ts @@ -0,0 +1,2 @@ +export const quoteResponse = () => Response.json({}) +export const swapResponse = () => Response.json({}) diff --git a/k8s/chart/values.yaml b/k8s/chart/values.yaml index cad662d16e..1416eee395 100644 --- a/k8s/chart/values.yaml +++ b/k8s/chart/values.yaml @@ -1,68 +1,68 @@ chains: - # - name: "ethereum" - # id: "1" - # - name: "optimism" - # id: "10" - # - name: "cronos" - # id: "25" - # - name: "rootstock" - # id: "30" - # - name: "telos" - # id: "40" - # - name: "bsc" - # id: "56" - # - name: "gnosis" - # id: "100" - # - name: "thundercore" - # id: "108" - # - name: "fuse" - # id: "122" - # - name: "polygon" - # id: "137" - # - name: "bttc" - # id: "199" - # - name: "fantom" - # id: "250" - # - name: "boba" - # id: "288" - # - name: "filecoin" - # id: "314" - # - name: "polygon-zkevm" - # id: "1101" - # - name: "core" - # id: "1116" - # - name: "moonbeam" - # id: "1284" - # - name: "moonriver" - # id: "1285" - # - name: "metis" - # id: "1088" - # - name: "kava" - # id: "2222" - # - name: "zetachain" - # id: "7000" - # - name: "base" - # id: "8453" - # - name: "haqq" - # id: "11235" + - name: "ethereum" + id: "1" + - name: "optimism" + id: "10" + - name: "cronos" + id: "25" + - name: "rootstock" + id: "30" + - name: "telos" + id: "40" + - name: "bsc" + id: "56" + - name: "gnosis" + id: "100" + - name: "thundercore" + id: "108" + - name: "fuse" + id: "122" + - name: "polygon" + id: "137" + - name: "bttc" + id: "199" + - name: "fantom" + id: "250" + - name: "boba" + id: "288" + - name: "filecoin" + id: "314" + - name: "polygon-zkevm" + id: "1101" + - name: "core" + id: "1116" + - name: "moonbeam" + id: "1284" + - name: "moonriver" + id: "1285" + - name: "metis" + id: "1088" + - name: "kava" + id: "2222" + - name: "zetachain" + id: "7000" + - name: "base" + id: "8453" + - name: "haqq" + id: "11235" - name: "arbitrum" id: "42161" - # - name: "arbitrum-nova" - # id: "42170" - # - name: "celo" - # id: "42220" - # - name: "avalanche" - # id: "43114" - # - name: "linea" - # id: "59144" - # - name: "boba-bnb" - # id: "56288" - # - name: "blast" - # id: "81457" - # - name: "scroll" - # id: "534352" - # - name: "harmony" - # id: "1666600000" - # - name: "skale-europa" - # id: "2046399126" \ No newline at end of file + - name: "arbitrum-nova" + id: "42170" + - name: "celo" + id: "42220" + - name: "avalanche" + id: "43114" + - name: "linea" + id: "59144" + - name: "boba-bnb" + id: "56288" + - name: "blast" + id: "81457" + - name: "scroll" + id: "534352" + - name: "harmony" + id: "1666600000" + - name: "skale-europa" + id: "2046399126" \ No newline at end of file diff --git a/packages/sushi/src/types/api.ts b/packages/sushi/src/types/api.ts new file mode 100644 index 0000000000..336ce12bb9 --- /dev/null +++ b/packages/sushi/src/types/api.ts @@ -0,0 +1 @@ +export {} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index dec2700e7e..75ff580661 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1586,6 +1586,10 @@ importers: specifier: 3.23.8 version: 3.23.8 + packages/sushi/dist/_cjs: {} + + packages/sushi/dist/_esm: {} + packages/telemetry: devDependencies: '@tsconfig/esm': From 39209d35f7660a36271d22e5ab60adc4b460e6a0 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Tue, 6 Aug 2024 03:18:18 +0100 Subject: [PATCH 046/125] fix: use correct price in deps --- packages/react-query/src/hooks/trade/useTrade.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-query/src/hooks/trade/useTrade.ts b/packages/react-query/src/hooks/trade/useTrade.ts index 381548fa98..150162ca24 100644 --- a/packages/react-query/src/hooks/trade/useTrade.ts +++ b/packages/react-query/src/hooks/trade/useTrade.ts @@ -277,7 +277,7 @@ export const useTrade = (variables: UseTradeParams) => { chainId, fromToken, price, - tokenInPrice, + tokenOutPrice, slippagePercentage, toToken, gasPrice, From 624eb44f64ab91e2200301a9e9560778c421dc31 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Tue, 6 Aug 2024 03:51:16 +0100 Subject: [PATCH 047/125] fix: hide profile address when sm and use next image with cloudinary fetch --- apps/web/src/lib/wagmi/components/user-profile/index.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/apps/web/src/lib/wagmi/components/user-profile/index.tsx b/apps/web/src/lib/wagmi/components/user-profile/index.tsx index 8d47b1fa19..1ca7071232 100644 --- a/apps/web/src/lib/wagmi/components/user-profile/index.tsx +++ b/apps/web/src/lib/wagmi/components/user-profile/index.tsx @@ -2,10 +2,11 @@ import { useIsMounted } from '@sushiswap/hooks' import { InterfaceEventName, sendAnalyticsEvent } from '@sushiswap/telemetry' -import { useBreakpoint } from '@sushiswap/ui' +import { cloudinaryFetchLoader } from '@sushiswap/ui' import { Button } from '@sushiswap/ui' // import { JazzIcon } from '@sushiswap/ui' import { Popover, PopoverContent, PopoverTrigger } from '@sushiswap/ui' +import Image from 'next/image' import React, { FC, useState } from 'react' import { ChainId } from 'sushi/chain' import { shortenAddress } from 'sushi/format' @@ -23,7 +24,6 @@ interface ProfileProps { export const UserProfile: FC = () => { const isMounted = useIsMounted() - const { isSm } = useBreakpoint('sm') const [view, setView] = useState(ProfileView.Default) const chainId = useChainId() const { address, isConnected } = useAccount() @@ -51,17 +51,18 @@ export const UserProfile: FC = () => { Date: Tue, 6 Aug 2024 03:51:31 +0100 Subject: [PATCH 048/125] fix: missing key --- apps/web/src/lib/wagmi/components/user-profile/ConnectView.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/web/src/lib/wagmi/components/user-profile/ConnectView.tsx b/apps/web/src/lib/wagmi/components/user-profile/ConnectView.tsx index b4db071724..fd369560f2 100644 --- a/apps/web/src/lib/wagmi/components/user-profile/ConnectView.tsx +++ b/apps/web/src/lib/wagmi/components/user-profile/ConnectView.tsx @@ -78,6 +78,7 @@ export const ConnectView: FC<{ onSelect(): void }> = ({ onSelect }) => { {_connectors.map((connector) => ( Date: Tue, 6 Aug 2024 03:51:46 +0100 Subject: [PATCH 049/125] chore: disable covalent from balance api for now --- .../balance/v0/[chainId]/[address]/route.ts | 56 +++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/apps/web/src/app/(evm)/api/balance/v0/[chainId]/[address]/route.ts b/apps/web/src/app/(evm)/api/balance/v0/[chainId]/[address]/route.ts index 7938c0ce46..5bee0b7136 100644 --- a/apps/web/src/app/(evm)/api/balance/v0/[chainId]/[address]/route.ts +++ b/apps/web/src/app/(evm)/api/balance/v0/[chainId]/[address]/route.ts @@ -1,8 +1,8 @@ -import { ChainID as CovalentChainID } from '@covalenthq/client-sdk' +// import { ChainID as CovalentChainID } from '@covalenthq/client-sdk' import { publicWagmiConfig } from '@sushiswap/wagmi-config' import { createConfig, getBalance, readContracts } from '@wagmi/core' import zip from 'lodash.zip' -import { covalentClient } from 'src/lib/covalent' +// import { covalentClient } from 'src/lib/covalent' import { type ChainId } from 'sushi/chain' import { Address, erc20Abi } from 'viem' import { z } from 'zod' @@ -35,33 +35,33 @@ export async function GET( console.log('request', _req) const { chainId, address } = querySchema.parse(params) - try { - const { data } = - await covalentClient.BalanceService.getTokenBalancesForWalletAddress( - chainId as CovalentChainID, - address, - ) + // try { + // const { data } = + // await covalentClient.BalanceService.getTokenBalancesForWalletAddress( + // chainId as CovalentChainID, + // address, + // ) - return Response.json( - data.items.reduce( - (previousValue, currentValue) => { - if (currentValue.balance) { - previousValue[currentValue.contract_address] = - currentValue.balance.toString() - } - return previousValue - }, - {} as Record, - ), - { - headers: { - 'Cache-Control': 's-maxage=1, stale-while-revalidate=59', - }, - }, - ) - } catch (e) { - console.error("Couldn't fetch balances from covalent", e) - } + // return Response.json( + // data.items.reduce( + // (previousValue, currentValue) => { + // if (currentValue.balance) { + // previousValue[currentValue.contract_address] = + // currentValue.balance.toString() + // } + // return previousValue + // }, + // {} as Record, + // ), + // { + // headers: { + // 'Cache-Control': 's-maxage=1, stale-while-revalidate=59', + // }, + // }, + // ) + // } catch (e) { + // console.error("Couldn't fetch balances from covalent", e) + // } const res = await fetch(`https://tokens.sushi.com/v0/${chainId}/addresses`, { next: { revalidate: 3600 }, From c9dbe37d55db259c31201131505752250ff03c08 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Tue, 6 Aug 2024 04:09:58 +0100 Subject: [PATCH 050/125] feat: basic input component --- packages/ui/src/components/input.tsx | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 packages/ui/src/components/input.tsx diff --git a/packages/ui/src/components/input.tsx b/packages/ui/src/components/input.tsx new file mode 100644 index 0000000000..960ce987ce --- /dev/null +++ b/packages/ui/src/components/input.tsx @@ -0,0 +1,25 @@ +import * as React from 'react' + +import classNames from 'classnames' + +export interface InputProps + extends React.InputHTMLAttributes {} + +const Input = React.forwardRef( + ({ className, type, ...props }, ref) => { + return ( + + ) + }, +) +Input.displayName = 'Input' + +export { Input } From 2049c0cc99aa58f0482e9ff355a2b7c3f1aeb79c Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Tue, 6 Aug 2024 04:37:00 +0100 Subject: [PATCH 051/125] feat: show $0 fee for stable and wrap and default back to non-usd if price is not available --- .../ui/swap/simple/simple-swap-trade-stats.tsx | 8 ++++---- packages/react-query/src/hooks/trade/useTrade.ts | 15 +++++++++------ 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/apps/web/src/ui/swap/simple/simple-swap-trade-stats.tsx b/apps/web/src/ui/swap/simple/simple-swap-trade-stats.tsx index 18f6372757..7792a852f2 100644 --- a/apps/web/src/ui/swap/simple/simple-swap-trade-stats.tsx +++ b/apps/web/src/ui/swap/simple/simple-swap-trade-stats.tsx @@ -98,7 +98,7 @@ export const SimpleSwapTradeStats: FC = () => { {loading || !trade?.fee ? ( ) : ( - `$${trade?.fee}` + `${trade?.fee}` )}
    @@ -113,9 +113,9 @@ export const SimpleSwapTradeStats: FC = () => { ) : loading || !trade?.gasSpent || trade.gasSpent === '0' ? ( ) : trade?.gasSpent ? ( - `${trade.gasSpent} ${Native.onChain(chainId).symbol} ($${ - trade.gasSpentUsd - })` + `${trade.gasSpent} ${Native.onChain(chainId).symbol} ${ + trade?.gasSpentUsd ? `($$${trade.gasSpentUsd})` : '' + }` ) : null}
    diff --git a/packages/react-query/src/hooks/trade/useTrade.ts b/packages/react-query/src/hooks/trade/useTrade.ts index 150162ca24..2df7b3f76b 100644 --- a/packages/react-query/src/hooks/trade/useTrade.ts +++ b/packages/react-query/src/hooks/trade/useTrade.ts @@ -5,6 +5,7 @@ import { } from '@sushiswap/telemetry' import { useQuery } from '@tanstack/react-query' import { useCallback, useMemo } from 'react' +import { isStable, isWrapOrUnwrap } from 'sushi' import { slippageAmount } from 'sushi/calculate' import { ChainId } from 'sushi/chain' import { @@ -237,12 +238,14 @@ export const useTrade = (variables: UseTradeParams) => { price && gasSpent ? gasSpent.multiply(price.asFraction).toSignificant(4) : undefined, - fee: tokenOutPrice - ? minAmountOut - .multiply(new Percent(25, 10000)) - .multiply(tokenOutPrice.asFraction) - .toSignificant(4) - : undefined, + fee: + !isWrapOrUnwrap({ fromToken, toToken }) && + !isStable({ fromToken, toToken }) + ? `${tokenOutPrice ? '$' : ''}${minAmountOut + .multiply(new Percent(25, 10000)) + .multiply(tokenOutPrice ? tokenOutPrice.asFraction : 1) + .toSignificant(4)} ${!tokenOutPrice ? toToken.symbol : ''}` + : '$0', route: data.route, functionName: isOffset ? 'transferValueAndprocessRoute' From ac1e130fff17db5178f89d1f72df31f74cbf887e Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Tue, 6 Aug 2024 04:57:11 +0100 Subject: [PATCH 052/125] feat: allow price impact to be passed instead of string --- .../web3-input/Currency/CurrencyInput.tsx | 12 ++--- .../web3-input/Currency/PricePanel.tsx | 52 ++++++++----------- .../swap/simple/simple-swap-token1-input.tsx | 1 + 3 files changed, 28 insertions(+), 37 deletions(-) diff --git a/apps/web/src/lib/wagmi/components/web3-input/Currency/CurrencyInput.tsx b/apps/web/src/lib/wagmi/components/web3-input/Currency/CurrencyInput.tsx index a783943300..624c309d31 100644 --- a/apps/web/src/lib/wagmi/components/web3-input/Currency/CurrencyInput.tsx +++ b/apps/web/src/lib/wagmi/components/web3-input/Currency/CurrencyInput.tsx @@ -1,5 +1,6 @@ 'use client' +import { useIsMounted } from '@sushiswap/hooks' import { usePrice } from '@sushiswap/react-query' import { Button, SelectIcon, TextField, classNames } from '@sushiswap/ui' import { Currency } from '@sushiswap/ui' @@ -12,12 +13,11 @@ import { useState, useTransition, } from 'react' +import { useBalanceWeb3 } from 'src/lib/wagmi/hooks/balances/useBalanceWeb3' import { ChainId } from 'sushi/chain' import { Token, Type, tryParseAmount } from 'sushi/currency' +import { Percent } from 'sushi/math' import { useAccount } from 'wagmi' - -import { useIsMounted } from '@sushiswap/hooks' -import { useBalanceWeb3 } from 'src/lib/wagmi/hooks/balances/useBalanceWeb3' import { TokenSelector } from '../../token-selector/TokenSelector' import { BalancePanel } from './BalancePanel' import { PricePanel } from './PricePanel' @@ -32,7 +32,7 @@ interface CurrencyInputProps { chainId: ChainId className?: string loading?: boolean - usdPctChange?: number + priceImpact?: Percent | undefined disableMaxButton?: boolean type: 'INPUT' | 'OUTPUT' fetching?: boolean @@ -57,7 +57,7 @@ const CurrencyInput: FC = ({ chainId, className, loading, - usdPctChange, + priceImpact, disableMaxButton = false, type, fetching, @@ -272,7 +272,7 @@ const CurrencyInput: FC = ({ & { error?: string price: Fraction | undefined @@ -18,7 +22,7 @@ export const PricePanel: FC = ({ price, currency, value, - usdPctChange, + priceImpact, error, }) => { const parsedValue = useMemo( @@ -56,35 +60,21 @@ export const PricePanel: FC = ({ $ {big}.{portion} )} - {!(!loading && price?.equalTo(ZERO)) && - usdPctChange && - usdPctChange !== 0 && ( - 0 - ? 'text-green' - : usdPctChange < -5 - ? 'text-red' - : usdPctChange < -3 - ? 'text-yellow' - : 'text-slate-500', - )} - > - {' '} - {`${ - usdPctChange?.toFixed(2) === '0.00' - ? '' - : usdPctChange > 0 - ? '(+' - : '(' - }${ - usdPctChange?.toFixed(2) === '0.00' - ? '' - : `${usdPctChange?.toFixed(2)}%)` - }`} - - )} + {!(!loading && price?.equalTo(ZERO)) && priceImpact && ( + + {priceImpact?.lessThan(ZERO) + ? '+' + : priceImpact?.greaterThan(ZERO) + ? '-' + : ''} + {Math.abs(Number(priceImpact?.toFixed(2)) || 0)}% + + )}

    ) } diff --git a/apps/web/src/ui/swap/simple/simple-swap-token1-input.tsx b/apps/web/src/ui/swap/simple/simple-swap-token1-input.tsx index 85812c7dc5..941d7c1d78 100644 --- a/apps/web/src/ui/swap/simple/simple-swap-token1-input.tsx +++ b/apps/web/src/ui/swap/simple/simple-swap-token1-input.tsx @@ -35,6 +35,7 @@ export const SimpleSwapToken1Input = () => { disableMaxButton currencyLoading={tokenLoading} allowNative={isWNativeSupported(chainId)} + // priceImpact={trade?.priceImpact} /> ) } From a1751a4c9408098e6eca8ce6e360fabd0c2a259f Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Tue, 6 Aug 2024 04:58:47 +0100 Subject: [PATCH 053/125] fix: remove dupe dollar symbol --- apps/web/src/ui/swap/simple/simple-swap-trade-stats.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web/src/ui/swap/simple/simple-swap-trade-stats.tsx b/apps/web/src/ui/swap/simple/simple-swap-trade-stats.tsx index 7792a852f2..d8ff77eb11 100644 --- a/apps/web/src/ui/swap/simple/simple-swap-trade-stats.tsx +++ b/apps/web/src/ui/swap/simple/simple-swap-trade-stats.tsx @@ -114,7 +114,7 @@ export const SimpleSwapTradeStats: FC = () => { ) : trade?.gasSpent ? ( `${trade.gasSpent} ${Native.onChain(chainId).symbol} ${ - trade?.gasSpentUsd ? `($$${trade.gasSpentUsd})` : '' + trade?.gasSpentUsd ? `($${trade.gasSpentUsd})` : '' }` ) : null} From ec8c9318e7b184317f672351771a883befa6176f Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Tue, 6 Aug 2024 09:07:05 +0100 Subject: [PATCH 054/125] chore: route group legal --- apps/web/src/app/{ => (legal)}/privacy-policy/layout.tsx | 2 +- apps/web/src/app/{ => (legal)}/privacy-policy/page.tsx | 0 apps/web/src/app/{ => (legal)}/terms-of-service/layout.tsx | 2 +- apps/web/src/app/{ => (legal)}/terms-of-service/page.tsx | 0 4 files changed, 2 insertions(+), 2 deletions(-) rename apps/web/src/app/{ => (legal)}/privacy-policy/layout.tsx (84%) rename apps/web/src/app/{ => (legal)}/privacy-policy/page.tsx (100%) rename apps/web/src/app/{ => (legal)}/terms-of-service/layout.tsx (84%) rename apps/web/src/app/{ => (legal)}/terms-of-service/page.tsx (100%) diff --git a/apps/web/src/app/privacy-policy/layout.tsx b/apps/web/src/app/(legal)/privacy-policy/layout.tsx similarity index 84% rename from apps/web/src/app/privacy-policy/layout.tsx rename to apps/web/src/app/(legal)/privacy-policy/layout.tsx index 774cc651ee..da0c375419 100644 --- a/apps/web/src/app/privacy-policy/layout.tsx +++ b/apps/web/src/app/(legal)/privacy-policy/layout.tsx @@ -1,6 +1,6 @@ import { Navigation } from '@sushiswap/ui' import { Metadata } from 'next' -import { headerElements } from '../(evm)/_common/header-elements' +import { headerElements } from '../../(evm)/_common/header-elements' export const metadata: Metadata = { title: 'Privacy Policy', diff --git a/apps/web/src/app/privacy-policy/page.tsx b/apps/web/src/app/(legal)/privacy-policy/page.tsx similarity index 100% rename from apps/web/src/app/privacy-policy/page.tsx rename to apps/web/src/app/(legal)/privacy-policy/page.tsx diff --git a/apps/web/src/app/terms-of-service/layout.tsx b/apps/web/src/app/(legal)/terms-of-service/layout.tsx similarity index 84% rename from apps/web/src/app/terms-of-service/layout.tsx rename to apps/web/src/app/(legal)/terms-of-service/layout.tsx index ecf29a4e4d..f626c01e2b 100644 --- a/apps/web/src/app/terms-of-service/layout.tsx +++ b/apps/web/src/app/(legal)/terms-of-service/layout.tsx @@ -1,6 +1,6 @@ import { Navigation } from '@sushiswap/ui' import { Metadata } from 'next' -import { headerElements } from '../(evm)/_common/header-elements' +import { headerElements } from '../../(evm)/_common/header-elements' export const metadata: Metadata = { title: 'Terms Of Service', diff --git a/apps/web/src/app/terms-of-service/page.tsx b/apps/web/src/app/(legal)/terms-of-service/page.tsx similarity index 100% rename from apps/web/src/app/terms-of-service/page.tsx rename to apps/web/src/app/(legal)/terms-of-service/page.tsx From 263844ebd03072895d1fad08690db5f678751a40 Mon Sep 17 00:00:00 2001 From: Ilya Lyalin Date: Tue, 6 Aug 2024 15:19:15 +0300 Subject: [PATCH 055/125] fix: Curve pool serialization(refuse+originalRates) + creation issue --- .../src/router/PoolBinarySerialization.ts | 11 ++++- .../sushi/src/tines/CurveMultitokenPool.ts | 41 +++++++++++-------- 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/packages/sushi/src/router/PoolBinarySerialization.ts b/packages/sushi/src/router/PoolBinarySerialization.ts index 654c981b08..fab7c4d837 100644 --- a/packages/sushi/src/router/PoolBinarySerialization.ts +++ b/packages/sushi/src/router/PoolBinarySerialization.ts @@ -28,6 +28,7 @@ enum PoolTypeIndex { Classic = 1, Concentrated = 2, Curve = 3, + CurvePoolCoreHaveBeenSerialized = 255, } const FEE_FRACTIONS = 10_000_000 @@ -101,17 +102,21 @@ export function serializePoolsBinary( } else if (pc instanceof CurvePoolCode) { const p = pc.pool as CurveMultitokenPool const core = p.core - if (CurveCoreSerialized.has(core.address)) return + if (CurveCoreSerialized.has(core.address)) { + stream.uint8(PoolTypeIndex.CurvePoolCoreHaveBeenSerialized) + return + } CurveCoreSerialized.add(core.address) stream.uint8(PoolTypeIndex.Curve) stream.uint8(curvePoolType2Num(pc.poolType)) stream.address(core.address) stream.uint8(core.tokens.length) + const originalRates = core.getOriginalRates() core.tokens.forEach((t, i) => { stream.uint24(tokenIndex.get(t.address) as number) stream.bigUInt(core.reserves[i] as bigint, core.address) - stream.float64(core.rates[i] as number) + stream.float64(originalRates[i] as number) }) stream.uint24(p.fee * FEE_FRACTIONS) // can be optimized - usually [0.003, 0.001, 0.0005] stream.float64(core.A) @@ -203,6 +208,8 @@ export function deserializePoolsBinary( }) break } + case PoolTypeIndex.CurvePoolCoreHaveBeenSerialized: // pools of one core are serialized only once + break default: console.error(`Deserealization: unknown pool type ${poolType}`) } diff --git a/packages/sushi/src/tines/CurveMultitokenPool.ts b/packages/sushi/src/tines/CurveMultitokenPool.ts index 4e8bf13817..cfed8e6ec9 100644 --- a/packages/sushi/src/tines/CurveMultitokenPool.ts +++ b/packages/sushi/src/tines/CurveMultitokenPool.ts @@ -16,22 +16,22 @@ export class CurveMultitokenPool extends RPool { flow1 = 0 constructor(core: CurveMultitokenCore, index0: number, index1: number) { - if (core) { - super( - core.address as Address, - core.tokens[index0] as RToken, - core.tokens[index1] as RToken, - core.fee, - core.reserves[index0] as bigint, - core.reserves[index1] as bigint, - MIN_LIQUIDITY, - SWAP_GAS_COST, - ) - console.assert(index0 < index1, 'Wrong CurveMultitokenPool indexes') - this.core = core - this.index0 = index0 - this.index1 = index1 - } else { + //if (core) { + super( + core?.address as Address, + core?.tokens[index0] as RToken, + core?.tokens[index1] as RToken, + core?.fee, + core?.reserves[index0] as bigint, + core?.reserves[index1] as bigint, + MIN_LIQUIDITY, + SWAP_GAS_COST, + ) + console.assert(index0 < index1, 'Wrong CurveMultitokenPool indexes') + this.core = core + this.index0 = index0 + this.index1 = index1 + /*} else { // for deserealization super( undefined as unknown as Address, @@ -43,7 +43,7 @@ export class CurveMultitokenPool extends RPool { MIN_LIQUIDITY, SWAP_GAS_COST, ) - } + }*/ } override updateReserves(_res0: bigint, _res1: bigint) { @@ -335,6 +335,13 @@ export class CurveMultitokenCore { cleanTmpData() { this.currentFlow = this.reserves.map(() => 0) } + + getOriginalRates(): number[] { + const decimalsMax = Math.max(...this.tokens.map((t) => t.decimals)) + return this.rates.map( + (r, i) => r / 10 ** (decimalsMax - this.tokens[i].decimals), + ) + } } export function createCurvePoolsForMultipool( From e36d79786f3050a13d60fb3f48b0dc0e7a856b71 Mon Sep 17 00:00:00 2001 From: LufyCZ Date: Wed, 7 Aug 2024 00:49:40 +0200 Subject: [PATCH 056/125] chore(apps/web): furo redirect --- apps/web/next.config.mjs | 20 +++++++++++--------- pnpm-lock.yaml | 5 +---- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/apps/web/next.config.mjs b/apps/web/next.config.mjs index deaebdc6b5..91b58311a9 100644 --- a/apps/web/next.config.mjs +++ b/apps/web/next.config.mjs @@ -7,7 +7,7 @@ const bundleAnalyzer = withBundleAnalyzer({ enabled: false && process.env.NODE_ENV !== 'development', }) -const FURO_URL = 'https://furo.sushi.com' +const FURO_URL = 'https://pay.sushi.com' /** @type {import('next').NextConfig} */ const nextConfig = bundleAnalyzer({ @@ -68,6 +68,16 @@ const nextConfig = bundleAnalyzer({ permanent: true, destination: '/swap?chainId=2046399126', }, + { + source: '/furo', + permanent: true, + destination: `${FURO_URL}`, + }, + { + source: '/furo/:path*', + permanent: true, + destination: `${FURO_URL}/:path*`, + }, ] }, async rewrites() { @@ -94,14 +104,6 @@ const nextConfig = bundleAnalyzer({ // ], // destination: '/pay/:path*', // }, - { - source: '/furo', - destination: `${FURO_URL}/furo`, - }, - { - source: '/furo/:path*', - destination: `${FURO_URL}/furo/:path*`, - }, ] }, }) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 75ff580661..8899761fcf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1586,10 +1586,6 @@ importers: specifier: 3.23.8 version: 3.23.8 - packages/sushi/dist/_cjs: {} - - packages/sushi/dist/_esm: {} - packages/telemetry: devDependencies: '@tsconfig/esm': @@ -22154,6 +22150,7 @@ packages: web3-provider-engine@14.2.1: resolution: {integrity: sha512-iSv31h2qXkr9vrL6UZDm4leZMc32SjWJFGOp/D92JXfcEboCqraZyuExDkpxKw8ziTufXieNM7LSXNHzszYdJw==} + deprecated: 'This package has been deprecated, see the README for details: https://github.com/MetaMask/web3-provider-engine' web3-providers-http@1.10.3: resolution: {integrity: sha512-6dAgsHR3MxJ0Qyu3QLFlQEelTapVfWNTu5F45FYh8t7Y03T1/o+YAkVxsbY5AdmD+y5bXG/XPJ4q8tjL6MgZHw==} From bcc416e49a4b4769a44041fa9909ff65855edf66 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Wed, 7 Aug 2024 00:45:59 +0100 Subject: [PATCH 057/125] fix: optionally pass to param --- packages/react-query/src/hooks/trade/useTrade.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-query/src/hooks/trade/useTrade.ts b/packages/react-query/src/hooks/trade/useTrade.ts index 2df7b3f76b..1debeb7915 100644 --- a/packages/react-query/src/hooks/trade/useTrade.ts +++ b/packages/react-query/src/hooks/trade/useTrade.ts @@ -96,7 +96,7 @@ export const useTradeQuery = ( params.searchParams.set('amount', `${amount?.quotient.toString()}`) params.searchParams.set('maxSlippage', `${+slippagePercentage / 100}`) params.searchParams.set('gasPrice', `${gasPrice}`) - params.searchParams.set('to', `${recipient}`) + recipient && params.searchParams.set('to', `${recipient}`) params.searchParams.set('preferSushi', 'true') params.searchParams.set('enableFee', 'true') params.searchParams.set( From 7e7e680315be9b78b44b5abe81f7ba2e74f5af4a Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Wed, 7 Aug 2024 00:46:33 +0100 Subject: [PATCH 058/125] fix: dont check type needlessly --- apis/router/src/handlers/swap2/schema.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apis/router/src/handlers/swap2/schema.ts b/apis/router/src/handlers/swap2/schema.ts index 70dfc2381a..08b11fcad8 100644 --- a/apis/router/src/handlers/swap2/schema.ts +++ b/apis/router/src/handlers/swap2/schema.ts @@ -28,7 +28,7 @@ export const querySchema5 = z.object({ .default(RouterLiquiditySource.Sender), to: z.optional( z.custom
    ( - (val) => typeof val === 'string' && isAddressFast(val), + (val) => isAddressFast(val), (val) => ({ message: `Incorrect address for 'to': ${val}` }), ), ), From a242ff20ff03a08e0736cb460352620f16ab607e Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Wed, 7 Aug 2024 00:46:52 +0100 Subject: [PATCH 059/125] fix: isStable equality --- packages/sushi/src/router/router.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/sushi/src/router/router.ts b/packages/sushi/src/router/router.ts index bc537b1b09..761ad34922 100644 --- a/packages/sushi/src/router/router.ts +++ b/packages/sushi/src/router/router.ts @@ -114,11 +114,11 @@ export const isStable = ({ fromToken, toToken, }: { fromToken: Type; toToken: Type }) => { - const fromTokenIsStable = STABLES[fromToken.chainId].some( - (t: Token) => t === fromToken.wrapped, + const fromTokenIsStable = STABLES[fromToken.chainId].some((t: Token) => + t.equals(fromToken), ) - const toTokenIsStable = STABLES[toToken.chainId].some( - (t: Token) => t === toToken.wrapped, + const toTokenIsStable = STABLES[toToken.chainId].some((t: Token) => + t.equals(toToken), ) return fromTokenIsStable && toTokenIsStable } From d6f52ae36cdc5be8f5492432137b377ff7e53923 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Wed, 7 Aug 2024 02:15:00 +0100 Subject: [PATCH 060/125] chore: remove bonds --- apps/web/src/app/(evm)/_common/header-elements.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/web/src/app/(evm)/_common/header-elements.ts b/apps/web/src/app/(evm)/_common/header-elements.ts index ae9a05b80f..bb2274abab 100644 --- a/apps/web/src/app/(evm)/_common/header-elements.ts +++ b/apps/web/src/app/(evm)/_common/header-elements.ts @@ -67,12 +67,12 @@ export const headerElements: NavigationElement[] = [ show: 'desktop', type: NavigationElementType.Single, }, - { - title: 'Bonds', - href: '/bonds', - show: 'desktop', - type: NavigationElementType.Single, - }, + // { + // title: 'Bonds', + // href: '/bonds', + // show: 'desktop', + // type: NavigationElementType.Single, + // }, { title: 'Stake', href: '/stake', From e10952ee088831ae12957a31a91759676a26738f Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Wed, 7 Aug 2024 02:15:37 +0100 Subject: [PATCH 061/125] chore: comment --- apis/router/src/handlers/swap2/index.ts | 12 ++++------- .../react-query/src/hooks/trade/useTrade.ts | 20 ++++++++++--------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/apis/router/src/handlers/swap2/index.ts b/apis/router/src/handlers/swap2/index.ts index b2e73710ce..0beb29048d 100644 --- a/apis/router/src/handlers/swap2/index.ts +++ b/apis/router/src/handlers/swap2/index.ts @@ -10,9 +10,8 @@ import { Router, RouterLiquiditySource, TransferValue, - isStable, - isUnwrap, - isWrap, + // isStable, + isWrapOrUnwrap, makeAPI02Object, } from 'sushi/router' import { MultiRoute, getBigInt } from 'sushi/tines' @@ -132,11 +131,8 @@ const handler = ( const chargeFee = enableFee && - !( - isWrap({ fromToken: tokenIn, toToken: tokenOut }) || - isUnwrap({ fromToken: tokenIn, toToken: tokenOut }) - ) && - !isStable({ fromToken: tokenIn, toToken: tokenOut }) + !isWrapOrUnwrap({ fromToken: tokenIn, toToken: tokenOut }) + // && !isStable({ fromToken: tokenIn, toToken: tokenOut }) if (chargeFee && chargeFeeBy === TransferValue.Input) { processFunction = ProcessFunction.ProcessRouteWithTransferValueInput diff --git a/packages/react-query/src/hooks/trade/useTrade.ts b/packages/react-query/src/hooks/trade/useTrade.ts index 1debeb7915..f8e645c008 100644 --- a/packages/react-query/src/hooks/trade/useTrade.ts +++ b/packages/react-query/src/hooks/trade/useTrade.ts @@ -5,7 +5,10 @@ import { } from '@sushiswap/telemetry' import { useQuery } from '@tanstack/react-query' import { useCallback, useMemo } from 'react' -import { isStable, isWrapOrUnwrap } from 'sushi' +import { + // isStable, + isWrapOrUnwrap, +} from 'sushi' import { slippageAmount } from 'sushi/calculate' import { ChainId } from 'sushi/chain' import { @@ -238,14 +241,13 @@ export const useTrade = (variables: UseTradeParams) => { price && gasSpent ? gasSpent.multiply(price.asFraction).toSignificant(4) : undefined, - fee: - !isWrapOrUnwrap({ fromToken, toToken }) && - !isStable({ fromToken, toToken }) - ? `${tokenOutPrice ? '$' : ''}${minAmountOut - .multiply(new Percent(25, 10000)) - .multiply(tokenOutPrice ? tokenOutPrice.asFraction : 1) - .toSignificant(4)} ${!tokenOutPrice ? toToken.symbol : ''}` - : '$0', + fee: !isWrapOrUnwrap({ fromToken, toToken }) + ? // && !isStable({ fromToken, toToken }) + `${tokenOutPrice ? '$' : ''}${minAmountOut + .multiply(new Percent(25, 10000)) + .multiply(tokenOutPrice ? tokenOutPrice.asFraction : 1) + .toSignificant(4)} ${!tokenOutPrice ? toToken.symbol : ''}` + : '$0', route: data.route, functionName: isOffset ? 'transferValueAndprocessRoute' From 2ba152d1e1b0cd53a3f123df29f9dd75ae411fe4 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Wed, 7 Aug 2024 05:16:26 +0100 Subject: [PATCH 062/125] chore: check lsd --- apis/router/src/handlers/swap2/index.ts | 8 ++- .../react-query/src/hooks/trade/useTrade.ts | 21 +++--- packages/sushi/src/config/lsds.ts | 64 ++++++++++++++++++- packages/sushi/src/config/stables.ts | 2 +- packages/sushi/src/router/router.ts | 15 +++++ 5 files changed, 93 insertions(+), 17 deletions(-) diff --git a/apis/router/src/handlers/swap2/index.ts b/apis/router/src/handlers/swap2/index.ts index 0beb29048d..3697fb6c6a 100644 --- a/apis/router/src/handlers/swap2/index.ts +++ b/apis/router/src/handlers/swap2/index.ts @@ -10,7 +10,8 @@ import { Router, RouterLiquiditySource, TransferValue, - // isStable, + isLsd, + isStable, isWrapOrUnwrap, makeAPI02Object, } from 'sushi/router' @@ -131,8 +132,9 @@ const handler = ( const chargeFee = enableFee && - !isWrapOrUnwrap({ fromToken: tokenIn, toToken: tokenOut }) - // && !isStable({ fromToken: tokenIn, toToken: tokenOut }) + !isWrapOrUnwrap({ fromToken: tokenIn, toToken: tokenOut }) && + !isStable({ fromToken: tokenIn, toToken: tokenOut }) && + isLsd({ fromToken: tokenIn, toToken: tokenOut }) if (chargeFee && chargeFeeBy === TransferValue.Input) { processFunction = ProcessFunction.ProcessRouteWithTransferValueInput diff --git a/packages/react-query/src/hooks/trade/useTrade.ts b/packages/react-query/src/hooks/trade/useTrade.ts index f8e645c008..4bf6800266 100644 --- a/packages/react-query/src/hooks/trade/useTrade.ts +++ b/packages/react-query/src/hooks/trade/useTrade.ts @@ -5,10 +5,6 @@ import { } from '@sushiswap/telemetry' import { useQuery } from '@tanstack/react-query' import { useCallback, useMemo } from 'react' -import { - // isStable, - isWrapOrUnwrap, -} from 'sushi' import { slippageAmount } from 'sushi/calculate' import { ChainId } from 'sushi/chain' import { @@ -20,6 +16,7 @@ import { } from 'sushi/config' import { Amount, Native, Price, type Type } from 'sushi/currency' import { Fraction, Percent, ZERO } from 'sushi/math' +import { isLsd, isStable, isWrapOrUnwrap } from 'sushi/router' import { type Address, type Hex, stringify, zeroAddress } from 'viem' import { usePrice } from '../prices' import { apiAdapter02To01 } from './apiAdapter' @@ -241,13 +238,15 @@ export const useTrade = (variables: UseTradeParams) => { price && gasSpent ? gasSpent.multiply(price.asFraction).toSignificant(4) : undefined, - fee: !isWrapOrUnwrap({ fromToken, toToken }) - ? // && !isStable({ fromToken, toToken }) - `${tokenOutPrice ? '$' : ''}${minAmountOut - .multiply(new Percent(25, 10000)) - .multiply(tokenOutPrice ? tokenOutPrice.asFraction : 1) - .toSignificant(4)} ${!tokenOutPrice ? toToken.symbol : ''}` - : '$0', + fee: + !isWrapOrUnwrap({ fromToken, toToken }) && + !isStable({ fromToken, toToken }) && + !isLsd({ fromToken, toToken }) + ? `${tokenOutPrice ? '$' : ''}${minAmountOut + .multiply(new Percent(25, 10000)) + .multiply(tokenOutPrice ? tokenOutPrice.asFraction : 1) + .toSignificant(4)} ${!tokenOutPrice ? toToken.symbol : ''}` + : '$0', route: data.route, functionName: isOffset ? 'transferValueAndprocessRoute' diff --git a/packages/sushi/src/config/lsds.ts b/packages/sushi/src/config/lsds.ts index 875fce51d7..72791b138f 100644 --- a/packages/sushi/src/config/lsds.ts +++ b/packages/sushi/src/config/lsds.ts @@ -1,5 +1,65 @@ import { ChainId } from '../chain/index.js' +import { Token } from '../currency/token.js' export const LSDS = { - [ChainId.ETHEREUM]: [], -} as const + [ChainId.ARBITRUM]: [], + [ChainId.ARBITRUM_NOVA]: [], + [ChainId.AVALANCHE]: [], + [ChainId.BASE]: [], + [ChainId.BOBA]: [], + [ChainId.BOBA_AVAX]: [], + [ChainId.BOBA_BNB]: [], + [ChainId.BSC]: [], + [ChainId.BTTC]: [], + [ChainId.CELO]: [], + [ChainId.ETHEREUM]: [ + new Token({ + chainId: ChainId.ETHEREUM, + address: '0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84', + decimals: 18, + symbol: 'StETH', + name: 'Lido Staked ETH', + }), + new Token({ + chainId: ChainId.ETHEREUM, + address: '0xae78736cd615f374d3085123a210448e74fc6393', + decimals: 18, + symbol: 'rETH', + name: 'Rocket Pool ETH', + }), + ], + [ChainId.FANTOM]: [], + [ChainId.FILECOIN]: [], + [ChainId.FUSE]: [], + [ChainId.GNOSIS]: [], + [ChainId.HARMONY]: [], + [ChainId.HAQQ]: [], + [ChainId.HECO]: [], + [ChainId.KAVA]: [], + [ChainId.LINEA]: [], + [ChainId.METIS]: [], + [ChainId.MOONBEAM]: [], + [ChainId.MOONRIVER]: [], + [ChainId.OKEX]: [], + [ChainId.OPTIMISM]: [], + [ChainId.POLYGON]: [], + [ChainId.POLYGON_ZKEVM]: [], + [ChainId.SCROLL]: [], + [ChainId.TELOS]: [], + [ChainId.THUNDERCORE]: [], + [ChainId.CORE]: [], + [ChainId.ZETACHAIN]: [], + [ChainId.CRONOS]: [], + [ChainId.BLAST]: [], + [ChainId.SKALE_EUROPA]: [], + [ChainId.ROOTSTOCK]: [], + [ChainId.PALM]: [], + [ChainId.ZKSYNC_ERA]: [], + // TESTNETS + [ChainId.POLYGON_TESTNET]: [], + [ChainId.FANTOM_TESTNET]: [], + [ChainId.BSC_TESTNET]: [], + [ChainId.ARBITRUM_TESTNET]: [], + [ChainId.AVALANCHE_TESTNET]: [], + [ChainId.SEPOLIA]: [], +} as const satisfies Record diff --git a/packages/sushi/src/config/stables.ts b/packages/sushi/src/config/stables.ts index 9b1d5f8b57..e75a14ae0b 100644 --- a/packages/sushi/src/config/stables.ts +++ b/packages/sushi/src/config/stables.ts @@ -235,4 +235,4 @@ export const STABLES = { [ChainId.ARBITRUM_TESTNET]: [], [ChainId.AVALANCHE_TESTNET]: [], [ChainId.SEPOLIA]: [], -} as const +} as const satisfies Record diff --git a/packages/sushi/src/router/router.ts b/packages/sushi/src/router/router.ts index 761ad34922..cf9e9d208f 100644 --- a/packages/sushi/src/router/router.ts +++ b/packages/sushi/src/router/router.ts @@ -123,6 +123,21 @@ export const isStable = ({ return fromTokenIsStable && toTokenIsStable } +export const isLsd = ({ + fromToken, + toToken, +}: { fromToken: Type; toToken: Type }) => { + const fromTokenIsLsd = STABLES[fromToken.chainId].some((t: Token) => + t.equals(fromToken), + ) + const toTokenIsLsd = STABLES[toToken.chainId].some((t: Token) => + t.equals(toToken), + ) + return ( + (fromToken.isNative && toTokenIsLsd) || (fromTokenIsLsd && toToken.isNative) + ) +} + export interface RPParams { tokenIn: Address amountIn: bigint From 12d221bf66b8e7fc12c5b6aec0db74b11f07c8e6 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Wed, 7 Aug 2024 05:48:05 +0100 Subject: [PATCH 063/125] chore: use trade cleanup, configure client trade and remove carbon offset --- .../lib/wagmi/hooks/trade/use-client-trade.ts | 113 ++++++++---------- .../derivedstate-simple-swap-provider.tsx | 2 +- .../simple-swap-trade-review-dialog.tsx | 9 +- .../swap/simple/simple-swap-trade-stats.tsx | 4 +- packages/react-query/src/hooks/trade/types.ts | 4 +- .../react-query/src/hooks/trade/useTrade.ts | 67 +++++------ packages/ui/src/components/settings/index.tsx | 6 +- pnpm-lock.yaml | 4 - 8 files changed, 98 insertions(+), 111 deletions(-) diff --git a/apps/web/src/lib/wagmi/hooks/trade/use-client-trade.ts b/apps/web/src/lib/wagmi/hooks/trade/use-client-trade.ts index 369f465d99..9fa2a98cf4 100644 --- a/apps/web/src/lib/wagmi/hooks/trade/use-client-trade.ts +++ b/apps/web/src/lib/wagmi/hooks/trade/use-client-trade.ts @@ -1,21 +1,22 @@ import { - UseTradeParams, - UseTradeReturnWriteArgs, + type UseTradeParams, + UseTradeReturn, usePrice, } from '@sushiswap/react-query' -import { useQuery } from '@tanstack/react-query' +import { UseQueryResult, useQuery } from '@tanstack/react-query' import { useMemo } from 'react' import { slippageAmount } from 'sushi/calculate' -import { ChainId } from 'sushi/chain' import { ROUTE_PROCESSOR_4_ADDRESS, + ROUTE_PROCESSOR_5_ADDRESS, isRouteProcessor4ChainId, + isRouteProcessor5ChainId, isWNativeSupported, } from 'sushi/config' import { Amount, Native, Price } from 'sushi/currency' import { Fraction, Percent } from 'sushi/math' import { Router } from 'sushi/router' -import { Address, Hex, zeroAddress } from 'viem' +import { zeroAddress } from 'viem' import { useGasPrice } from 'wagmi' import { usePoolsCodeMap } from '../pools/hooks/usePoolsCodeMap' @@ -25,7 +26,6 @@ export const useClientTrade = (variables: UseTradeParams) => { fromToken, toToken, slippagePercentage, - carbonOffset, amount, enabled, recipient, @@ -55,8 +55,6 @@ export const useClientTrade = (variables: UseTradeParams) => { withBentoPools: true, }) - // console.debug('fee data', feeData) - return useQuery({ queryKey: [ 'useClientTrade', @@ -90,9 +88,9 @@ export const useClientTrade = (variables: UseTradeParams) => { amountOut: undefined, minAmountOut: undefined, gasSpent: undefined, - writeArgs: undefined, + // writeArgs: undefined, route: undefined, - functionName: 'processRoute', + // functionName: 'processRoute', value: undefined, tokenTax: undefined, } @@ -107,31 +105,21 @@ export const useClientTrade = (variables: UseTradeParams) => { 1, // 5% impact before dex aggregation ) - // const logPools = Array.from(poolsCodeMap.values()) - // .map( - // (pc) => - // `* ${pc.liquidityProvider}/${pc.pool.token0.symbol}/${pc.pool.token1.symbol}-${pc.pool.fee}\n`, - // ) - // .join('') - // console.debug(` - // Pools found ${poolsCodeMap.size}: - // ${logPools} - // `) - - // const route = Router.findSushiRoute( - // poolsCodeMap, - // chainId, - // fromToken, - // BigNumber.from(amount.quotient.toString()), - // toToken, - // feeData.gasPrice.toNumber() - // ) - let args = undefined if (recipient) { - if (isRouteProcessor4ChainId(chainId)) { - // console.debug('routeProcessor4Params') + if (isRouteProcessor5ChainId(chainId)) { + args = Router.routeProcessor5Params( + poolsCodeMap, + route, + fromToken, + toToken, + recipient, + ROUTE_PROCESSOR_5_ADDRESS[chainId], + [], + +slippagePercentage / 100, + ) + } else if (isRouteProcessor4ChainId(chainId)) { args = Router.routeProcessor4Params( poolsCodeMap, route, @@ -162,32 +150,35 @@ export const useClientTrade = (variables: UseTradeParams) => { new Percent(Math.floor(+slippagePercentage * 100), 10_000), )[0], ) - const isOffset = chainId === ChainId.POLYGON && carbonOffset + // const isOffset = chainId === ChainId.POLYGON && carbonOffset + // // let writeArgs: UseTradeReturnWriteArgs = args // let writeArgs: UseTradeReturnWriteArgs = args - let writeArgs: UseTradeReturnWriteArgs = args - ? [ - args.tokenIn as Address, - args.amountIn, - args.tokenOut as Address, - args.amountOutMin, - args.to as Address, - args.routeCode as Hex, - ] - : undefined - - // const overrides = fromToken.isNative && writeArgs?.[1] ? { value: BigNumber.from(writeArgs?.[1]) } : undefined - let value = - fromToken.isNative && writeArgs?.[1] ? writeArgs[1] : undefined - - if (writeArgs && isOffset && chainId === ChainId.POLYGON) { - writeArgs = [ - '0xbc4a6be1285893630d45c881c6c343a65fdbe278', - 20000000000000000n, - ...writeArgs, - ] - value = (fromToken.isNative ? writeArgs[3] : 0n) + 20000000000000000n - } + // ? [ + // args.tokenIn as Address, + // args.amountIn, + // args.tokenOut as Address, + // args.amountOutMin, + // args.to as Address, + // args.routeCode as Hex, + // ] + // : undefined + + // // const overrides = fromToken.isNative && writeArgs?.[1] ? { value: BigNumber.from(writeArgs?.[1]) } : undefined + // let value = + // fromToken.isNative && writeArgs?.[1] ? writeArgs[1] : undefined + + // if (writeArgs && isOffset && chainId === ChainId.POLYGON) { + // writeArgs = [ + // '0xbc4a6be1285893630d45c881c6c343a65fdbe278', + // 20000000000000000n, + // ...writeArgs, + // ] + // value = (fromToken.isNative ? writeArgs[3] : 0n) + 20000000000000000n + // } + + const value = + fromToken.isNative && args?.amountIn ? args.amountIn : undefined // console.log({ writeArgs }) @@ -227,10 +218,10 @@ export const useClientTrade = (variables: UseTradeParams) => { // .toSignificant(4) // : undefined, route, - functionName: isOffset - ? 'transferValueAndprocessRoute' - : 'processRoute', - writeArgs, + // functionName: isOffset + // ? 'transferValueAndprocessRoute' + // : 'processRoute', + // writeArgs, value, txdata: args?.data, tokenTax, @@ -244,5 +235,5 @@ export const useClientTrade = (variables: UseTradeParams) => { enabled: Boolean( enabled && poolsCodeMap && gasPrice && fromToken && toToken && chainId, ), - }) + }) as UseQueryResult } diff --git a/apps/web/src/ui/swap/simple/derivedstate-simple-swap-provider.tsx b/apps/web/src/ui/swap/simple/derivedstate-simple-swap-provider.tsx index 142bf21f7f..8fc851c9ec 100644 --- a/apps/web/src/ui/swap/simple/derivedstate-simple-swap-provider.tsx +++ b/apps/web/src/ui/swap/simple/derivedstate-simple-swap-provider.tsx @@ -485,7 +485,7 @@ const useSimpleSwapTrade = () => { setTokenTax(undefined) }, [token0, token1, setTokenTax]) - return (useSwapApi ? apiTrade : clientTrade) as ReturnType + return (useSwapApi ? apiTrade : clientTrade) } export { diff --git a/apps/web/src/ui/swap/simple/simple-swap-trade-review-dialog.tsx b/apps/web/src/ui/swap/simple/simple-swap-trade-review-dialog.tsx index 05f0ff1ade..2172d16b2a 100644 --- a/apps/web/src/ui/swap/simple/simple-swap-trade-review-dialog.tsx +++ b/apps/web/src/ui/swap/simple/simple-swap-trade-review-dialog.tsx @@ -248,7 +248,7 @@ export const SimpleSwapTradeReviewDialog: FC<{ txHash: hash, exporerLink: Chain.txUrl(chainId, hash), route: stringify(trade?.route), - args: stringify(trade?.writeArgs), + txdata: stringify(trade?.txdata), }) } } else { @@ -308,7 +308,7 @@ export const SimpleSwapTradeReviewDialog: FC<{ chainId: chainId, txHash: hash, route: stringify(trade?.route), - args: stringify(trade?.writeArgs), + txdata: stringify(trade?.txdata), }) } } @@ -339,17 +339,18 @@ export const SimpleSwapTradeReviewDialog: FC<{ sendAnalyticsEvent(SwapEventName.SWAP_ERROR, { route: stringify(trade?.route), + data: stringify(trade?.txdata), error: e instanceof Error ? e.message : undefined, }) log.error('swap error', { route: stringify(trade?.route), - args: stringify(trade?.writeArgs), + data: stringify(trade?.txdata), error: stringify(e), }) createErrorToast(e.message, false) }, - [trade?.route, trade?.writeArgs], + [trade?.route, trade?.txdata], ) const { diff --git a/apps/web/src/ui/swap/simple/simple-swap-trade-stats.tsx b/apps/web/src/ui/swap/simple/simple-swap-trade-stats.tsx index d8ff77eb11..a9471b12ef 100644 --- a/apps/web/src/ui/swap/simple/simple-swap-trade-stats.tsx +++ b/apps/web/src/ui/swap/simple/simple-swap-trade-stats.tsx @@ -27,9 +27,9 @@ export const SimpleSwapTradeStats: FC = () => { const { state: { chainId, swapAmountString, recipient, forceClient }, } = useDerivedStateSimpleSwap() - const { isInitialLoading: isLoading, data: trade } = useSimpleSwapTrade() + const { isLoading, data: trade } = useSimpleSwapTrade() const { isFallback } = useFallback(chainId) - const loading = Boolean(isLoading && !trade?.writeArgs) + const loading = Boolean(isLoading && !trade) return ( | undefined gasSpent: string | undefined gasSpentUsd: string | undefined - functionName: 'processRoute' | 'transferValueAndprocessRoute' - writeArgs: UseTradeReturnWriteArgs + // functionName: 'processRoute' | 'transferValueAndprocessRoute' + // writeArgs: UseTradeReturnWriteArgs route: TradeType['route'] value?: bigint | undefined tokenTax: Percent | false | undefined diff --git a/packages/react-query/src/hooks/trade/useTrade.ts b/packages/react-query/src/hooks/trade/useTrade.ts index 4bf6800266..6708c1906e 100644 --- a/packages/react-query/src/hooks/trade/useTrade.ts +++ b/packages/react-query/src/hooks/trade/useTrade.ts @@ -17,14 +17,10 @@ import { import { Amount, Native, Price, type Type } from 'sushi/currency' import { Fraction, Percent, ZERO } from 'sushi/math' import { isLsd, isStable, isWrapOrUnwrap } from 'sushi/router' -import { type Address, type Hex, stringify, zeroAddress } from 'viem' +import { stringify, zeroAddress } from 'viem' import { usePrice } from '../prices' import { apiAdapter02To01 } from './apiAdapter' -import type { - UseTradeParams, - UseTradeQuerySelect, - UseTradeReturnWriteArgs, -} from './types' +import type { UseTradeParams, UseTradeQuerySelect } from './types' import { tradeValidator02 } from './validator02' export const TRADE_API_BASE_URL = @@ -145,7 +141,7 @@ export const useTrade = (variables: UseTradeParams) => { toToken, amount, slippagePercentage, - carbonOffset, + // carbonOffset, gasPrice, tokenTax, } = variables @@ -190,28 +186,31 @@ export const useTrade = (variables: UseTradeParams) => { new Percent(Math.floor(+slippagePercentage * 100), 10_000), )[0], ) - const isOffset = chainId === ChainId.POLYGON && carbonOffset - let writeArgs: UseTradeReturnWriteArgs = data?.args - ? ([ - data.args.tokenIn as Address, - data.args.amountIn, - data.args.tokenOut as Address, - data.args.amountOutMin, - data.args.to as Address, - data.args.routeCode as Hex, - ] as const) - : undefined - let value = fromToken.isNative ? writeArgs?.[1] ?? undefined : undefined + // const isOffset = chainId === ChainId.POLYGON && carbonOffset - if (writeArgs && isOffset && chainId === ChainId.POLYGON) { - writeArgs = [ - '0xbc4a6be1285893630d45c881c6c343a65fdbe278', - 20000000000000000n, - ...writeArgs, - ] - value = (fromToken.isNative ? writeArgs[3] : 0n) + 20000000000000000n - } + // let writeArgs: UseTradeReturnWriteArgs = data?.args + // ? ([ + // data.args.tokenIn as Address, + // data.args.amountIn, + // data.args.tokenOut as Address, + // data.args.amountOutMin, + // data.args.to as Address, + // data.args.routeCode as Hex, + // ] as const) + // : undefined + // let value = fromToken.isNative ? writeArgs?.[1] ?? undefined : undefined + + const value = fromToken.isNative ? data?.args?.amountIn : undefined + + // if (writeArgs && isOffset && chainId === ChainId.POLYGON) { + // writeArgs = [ + // '0xbc4a6be1285893630d45c881c6c343a65fdbe278', + // 20000000000000000n, + // ...writeArgs, + // ] + // value = (fromToken.isNative ? writeArgs[3] : 0n) + 20000000000000000n + // } const gasSpent = gasPrice ? Amount.fromRawAmount( @@ -248,10 +247,10 @@ export const useTrade = (variables: UseTradeParams) => { .toSignificant(4)} ${!tokenOutPrice ? toToken.symbol : ''}` : '$0', route: data.route, - functionName: isOffset - ? 'transferValueAndprocessRoute' - : 'processRoute', - writeArgs, + // functionName: isOffset + // ? 'transferValueAndprocessRoute' + // : 'processRoute', + // writeArgs, value, tokenTax, txdata: data.txdata, @@ -267,16 +266,16 @@ export const useTrade = (variables: UseTradeParams) => { gasSpent: undefined, gasSpentUsd: undefined, fee: undefined, - writeArgs: undefined, + // writeArgs: undefined, route: undefined, - functionName: 'processRoute', + // functionName: 'processRoute', value: undefined, tokenTax: undefined, txdata: undefined, } }, [ - carbonOffset, + // carbonOffset, amount, chainId, fromToken, diff --git a/packages/ui/src/components/settings/index.tsx b/packages/ui/src/components/settings/index.tsx index cd9e2335e5..c734437bd0 100644 --- a/packages/ui/src/components/settings/index.tsx +++ b/packages/ui/src/components/settings/index.tsx @@ -25,7 +25,7 @@ import { TooltipProvider, TooltipTrigger, } from '../tooltip' -import { CarbonOffset } from './CarbonOffset' +// import { CarbonOffset } from './CarbonOffset' import { ExpertMode } from './ExpertMode' import { SlippageTolerance } from './SlippageTolerance' import { TransactionDeadline } from './TransactionDeadline' @@ -127,9 +127,9 @@ export const SettingsOverlay: FC = ({ {modules.includes(SettingsModule.ExpertMode) && } - {modules.includes(SettingsModule.CarbonOffset) && ( + {/* {modules.includes(SettingsModule.CarbonOffset) && ( - )} + )} */} {modules.includes(SettingsModule.TransactionDeadline) && options?.transactionDeadline && ( diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 75ff580661..dec2700e7e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1586,10 +1586,6 @@ importers: specifier: 3.23.8 version: 3.23.8 - packages/sushi/dist/_cjs: {} - - packages/sushi/dist/_esm: {} - packages/telemetry: devDependencies: '@tsconfig/esm': From b2f809a0bd465dcd396091fe32453da6f1caadf5 Mon Sep 17 00:00:00 2001 From: matthewlilley Date: Wed, 7 Aug 2024 04:49:15 +0000 Subject: [PATCH 064/125] chore: format --- .../src/ui/swap/simple/derivedstate-simple-swap-provider.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web/src/ui/swap/simple/derivedstate-simple-swap-provider.tsx b/apps/web/src/ui/swap/simple/derivedstate-simple-swap-provider.tsx index 8fc851c9ec..814dbc0b38 100644 --- a/apps/web/src/ui/swap/simple/derivedstate-simple-swap-provider.tsx +++ b/apps/web/src/ui/swap/simple/derivedstate-simple-swap-provider.tsx @@ -485,7 +485,7 @@ const useSimpleSwapTrade = () => { setTokenTax(undefined) }, [token0, token1, setTokenTax]) - return (useSwapApi ? apiTrade : clientTrade) + return useSwapApi ? apiTrade : clientTrade } export { From a6b942069ab67bf65e34c6ef97c12f7529cb28da Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Wed, 7 Aug 2024 06:53:08 +0100 Subject: [PATCH 065/125] chore: prettify swap error page --- apps/web/src/app/(evm)/swap/error.tsx | 39 +++++++++++++++++++-------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/apps/web/src/app/(evm)/swap/error.tsx b/apps/web/src/app/(evm)/swap/error.tsx index 89193c2f97..5b6fe56366 100644 --- a/apps/web/src/app/(evm)/swap/error.tsx +++ b/apps/web/src/app/(evm)/swap/error.tsx @@ -1,6 +1,12 @@ 'use client' // Error components must be Client Components import * as Sentry from '@sentry/nextjs' +import { + Button, + Container, + classNames, + typographyVariants, +} from '@sushiswap/ui' import { useLogger } from 'next-axiom' import { useEffect } from 'react' @@ -21,17 +27,28 @@ export default function SwapError({ log.error('swap page error', error) }, [log, error]) return ( -
    -

    Something went wrong!

    - -
    + Something went wrong! + + +
    + +
    +
    + ) } From f5a13763e6552f002b2a47a43cd8c078fa8db755 Mon Sep 17 00:00:00 2001 From: 0xMasayoshi <0xMasayoshi@protonmail.com> Date: Wed, 7 Aug 2024 13:49:13 +0700 Subject: [PATCH 066/125] fix: currency input loading state --- .../components/web3-input/Currency/CurrencyInput.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/web/src/lib/wagmi/components/web3-input/Currency/CurrencyInput.tsx b/apps/web/src/lib/wagmi/components/web3-input/Currency/CurrencyInput.tsx index a783943300..a060db3790 100644 --- a/apps/web/src/lib/wagmi/components/web3-input/Currency/CurrencyInput.tsx +++ b/apps/web/src/lib/wagmi/components/web3-input/Currency/CurrencyInput.tsx @@ -151,7 +151,7 @@ const CurrencyInput: FC = ({ hideSearch={hideSearch} >
    Date: Wed, 7 Aug 2024 08:03:26 +0100 Subject: [PATCH 067/125] feat: calculat fee --- packages/sushi/src/calculate/fee.ts | 8 ++++++++ packages/sushi/src/calculate/index.ts | 1 + 2 files changed, 9 insertions(+) create mode 100644 packages/sushi/src/calculate/fee.ts diff --git a/packages/sushi/src/calculate/fee.ts b/packages/sushi/src/calculate/fee.ts new file mode 100644 index 0000000000..0d3590b285 --- /dev/null +++ b/packages/sushi/src/calculate/fee.ts @@ -0,0 +1,8 @@ +import type { Amount } from '../currency/amount.js' +import type { Type } from '../currency/type.js' +import { getBigInt } from '../tines/Utils.js' + +export const calculateFee = (amount: bigint | Amount, fee = 0.0025) => + ((typeof amount === 'bigint' ? amount : amount.quotient) * + getBigInt(fee * 1_000_000)) / + 1_000_000n diff --git a/packages/sushi/src/calculate/index.ts b/packages/sushi/src/calculate/index.ts index a691235599..3428b82ef9 100644 --- a/packages/sushi/src/calculate/index.ts +++ b/packages/sushi/src/calculate/index.ts @@ -1,2 +1,3 @@ +export { calculateFee } from './fee.js' export { gasMargin } from './gasMargin.js' export { slippageAmount } from './slippageAmount.js' From fd0262ee8a8f7e7840dd37189b2d057555f4e661 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Wed, 7 Aug 2024 08:04:34 +0100 Subject: [PATCH 068/125] chore: move make api object to api --- .../makeAPI02Object.ts => apis/router/src/make-api-object.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) rename packages/sushi/src/router/makeAPI02Object.ts => apis/router/src/make-api-object.ts (96%) diff --git a/packages/sushi/src/router/makeAPI02Object.ts b/apis/router/src/make-api-object.ts similarity index 96% rename from packages/sushi/src/router/makeAPI02Object.ts rename to apis/router/src/make-api-object.ts index 0bd1f5971f..52c9995c69 100644 --- a/packages/sushi/src/router/makeAPI02Object.ts +++ b/apis/router/src/make-api-object.ts @@ -1,11 +1,10 @@ +import type { LiquidityProviders, RPParams } from 'sushi/router' import { type MultiRoute, type RToken, type RouteLeg, RouteStatus, -} from '../tines/index.js' -import { LiquidityProviders } from './liquidity-providers/LiquidityProvider.js' -import type { RPParams } from './router.js' +} from 'sushi/tines' function makeAPI02Token(token: RToken) { return { From e55027968d8c8479b5ec13c7489660ffee2ee4e3 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Wed, 7 Aug 2024 08:07:46 +0100 Subject: [PATCH 069/125] chore: rm cross chain banner --- apps/web/src/ui/swap/swap-mode-buttons.tsx | 78 ++++++++++------------ 1 file changed, 34 insertions(+), 44 deletions(-) diff --git a/apps/web/src/ui/swap/swap-mode-buttons.tsx b/apps/web/src/ui/swap/swap-mode-buttons.tsx index 3a8601b7bf..982befb18a 100644 --- a/apps/web/src/ui/swap/swap-mode-buttons.tsx +++ b/apps/web/src/ui/swap/swap-mode-buttons.tsx @@ -1,6 +1,5 @@ 'use client' -import { useIsMounted, useLocalStorage } from '@sushiswap/hooks' import { CardContent, CardDescription, @@ -17,9 +16,6 @@ import Link from 'next/link' import { PathnameButton } from '../pathname-button' export const SwapModeButtons = () => { - const [bannerMinimized] = useLocalStorage('xswap-banner-minimized', false) - const isMounted = useIsMounted() - return (
    @@ -27,47 +23,41 @@ export const SwapModeButtons = () => { Swap - {bannerMinimized && isMounted ? ( - - - - - - - - - Cross Chain - - - - - + + + + + + + + + Cross Chain + + + + - - - Cross-chain Swap - - Swap tokens natively across 15 chains including Ethereum, - Arbitrum, Optimism, Polygon, Base and more! - - - - - Learn more. - - - - - ) : null} + + + + Cross-chain Swap + + Swap tokens natively across 15 chains including Ethereum, + Arbitrum, Optimism, Polygon, Base and more! + + + + + Learn more. + + + +
    ) } From 47b9ee9e48e1c50f870f63723ca94d7c478ab497 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Wed, 7 Aug 2024 08:08:48 +0100 Subject: [PATCH 070/125] refactor: trade hooks to return tx object and remove redundant data --- apis/router/src/handlers/swap/index.ts | 8 +- apis/router/src/handlers/swap2/index.ts | 4 +- apps/web/src/lib/hooks/useSimulateTrade.ts | 23 +- .../lib/wagmi/hooks/trade/use-client-trade.ts | 265 +++++++++--------- .../cross-chain/cross-chain-swap-widget.tsx | 2 +- .../simple/simple-swap-settings-overlay.tsx | 5 +- .../simple-swap-trade-review-dialog.tsx | 18 +- .../src/ui/swap/simple/simple-swap-widget.tsx | 2 +- packages/react-query/src/hooks/trade/types.ts | 12 +- .../react-query/src/hooks/trade/useTrade.ts | 60 ++-- packages/sushi/src/config/route-processor.ts | 3 +- packages/sushi/src/router/index.ts | 1 - 12 files changed, 197 insertions(+), 206 deletions(-) diff --git a/apis/router/src/handlers/swap/index.ts b/apis/router/src/handlers/swap/index.ts index 7c0e28d19a..d728b75a3e 100644 --- a/apis/router/src/handlers/swap/index.ts +++ b/apis/router/src/handlers/swap/index.ts @@ -8,12 +8,7 @@ import { RouteProcessor4ChainId, } from 'sushi/config' import { Type } from 'sushi/currency' -import { - NativeWrapProvider, - Router, - RouterLiquiditySource, - makeAPI02Object, -} from 'sushi/router' +import { NativeWrapProvider, Router, RouterLiquiditySource } from 'sushi/router' import { isAddressFast } from 'sushi/serializer' import { MultiRoute } from 'sushi/tines' import { Address } from 'viem' @@ -26,6 +21,7 @@ import { MAX_TIME_WITHOUT_NETWORK_UPDATE, POOL_FETCH_TIMEOUT, } from '../../config.js' +import { makeAPI02Object } from '../../make-api-object.js' import { querySchema3_2 } from './schema.js' const nativeProvider = new NativeWrapProvider( diff --git a/apis/router/src/handlers/swap2/index.ts b/apis/router/src/handlers/swap2/index.ts index 3697fb6c6a..cb3d28142b 100644 --- a/apis/router/src/handlers/swap2/index.ts +++ b/apis/router/src/handlers/swap2/index.ts @@ -13,7 +13,6 @@ import { isLsd, isStable, isWrapOrUnwrap, - makeAPI02Object, } from 'sushi/router' import { MultiRoute, getBigInt } from 'sushi/tines' import { Address } from 'viem' @@ -27,6 +26,7 @@ import { MAX_TIME_WITHOUT_NETWORK_UPDATE, POOL_FETCH_TIMEOUT, } from '../../config.js' +import { makeAPI02Object } from '../../make-api-object.js' // import { swapResponse } from './response.js' import { querySchema5 } from './schema.js' @@ -134,7 +134,7 @@ const handler = ( enableFee && !isWrapOrUnwrap({ fromToken: tokenIn, toToken: tokenOut }) && !isStable({ fromToken: tokenIn, toToken: tokenOut }) && - isLsd({ fromToken: tokenIn, toToken: tokenOut }) + !isLsd({ fromToken: tokenIn, toToken: tokenOut }) if (chargeFee && chargeFeeBy === TransferValue.Input) { processFunction = ProcessFunction.ProcessRouteWithTransferValueInput diff --git a/apps/web/src/lib/hooks/useSimulateTrade.ts b/apps/web/src/lib/hooks/useSimulateTrade.ts index f9be088da9..d71e370d72 100644 --- a/apps/web/src/lib/hooks/useSimulateTrade.ts +++ b/apps/web/src/lib/hooks/useSimulateTrade.ts @@ -1,10 +1,7 @@ import { UseTradeReturn } from '@sushiswap/react-query' import { useEffect, useMemo, useRef } from 'react' import { useDerivedStateSimpleSwap } from 'src/ui/swap/simple/derivedstate-simple-swap-provider' -import { - ROUTE_PROCESSOR_5_ADDRESS, - isRouteProcessor5ChainId, -} from 'sushi/config' +import { isRouteProcessor5ChainId } from 'sushi/config' import { CallErrorType, CallReturnType, Hex, RawContractError } from 'viem' import { useAccount, useCall } from 'wagmi' import { getTokenTax } from '../swap/getTokenTax' @@ -31,12 +28,10 @@ export function useSimulateTrade({ const simulateTrade = useCall({ chainId: chainId, - to: isRouteProcessor5ChainId(chainId) - ? ROUTE_PROCESSOR_5_ADDRESS[chainId] - : undefined, - data: trade?.txdata as Hex | undefined, + to: trade?.tx?.to, + data: trade?.tx?.data as Hex | undefined, account: address, - value: trade?.value || 0n, + value: trade?.tx?.value || 0n, query: { retry: (i, error) => { if ( @@ -51,7 +46,7 @@ export function useSimulateTrade({ enabled && Boolean( address && - trade?.txdata && + trade?.tx && isRouteProcessor5ChainId(chainId) && trade?.route?.status !== 'NoWay', ), @@ -99,11 +94,9 @@ export function useSimulateTrade({ ? { ...simulateTrade.data, request: { - to: isRouteProcessor5ChainId(chainId) - ? ROUTE_PROCESSOR_5_ADDRESS[chainId] - : undefined, - data: trade?.txdata as Hex | undefined, - value: trade?.value || 0n, + to: trade?.tx?.to, + data: trade?.tx?.data as Hex | undefined, + value: trade?.tx?.value || 0n, account: address, }, } diff --git a/apps/web/src/lib/wagmi/hooks/trade/use-client-trade.ts b/apps/web/src/lib/wagmi/hooks/trade/use-client-trade.ts index 9fa2a98cf4..383df9dbc2 100644 --- a/apps/web/src/lib/wagmi/hooks/trade/use-client-trade.ts +++ b/apps/web/src/lib/wagmi/hooks/trade/use-client-trade.ts @@ -4,18 +4,27 @@ import { usePrice, } from '@sushiswap/react-query' import { UseQueryResult, useQuery } from '@tanstack/react-query' +import { is } from 'date-fns/locale' import { useMemo } from 'react' -import { slippageAmount } from 'sushi/calculate' +import { getBigInt } from 'sushi' +import { calculateFee, slippageAmount } from 'sushi/calculate' import { - ROUTE_PROCESSOR_4_ADDRESS, + MULTISIG_ADDRESS, ROUTE_PROCESSOR_5_ADDRESS, - isRouteProcessor4ChainId, + isMultisigChainId, isRouteProcessor5ChainId, isWNativeSupported, } from 'sushi/config' import { Amount, Native, Price } from 'sushi/currency' import { Fraction, Percent } from 'sushi/math' -import { Router } from 'sushi/router' +import { + ProcessFunction, + Router, + RouterLiquiditySource, + isLsd, + isStable, + isWrapOrUnwrap, +} from 'sushi/router' import { zeroAddress } from 'viem' import { useGasPrice } from 'wagmi' import { usePoolsCodeMap } from '../pools/hooks/usePoolsCodeMap' @@ -47,6 +56,11 @@ export const useClientTrade = (variables: UseTradeParams) => { : _price }, [_price, chainId]) + const { data: tokenOutPrice } = usePrice({ + chainId, + address: toToken?.wrapped.address, + }) + const { data: poolsCodeMap } = usePoolsCodeMap({ chainId, currencyA: fromToken, @@ -72,68 +86,59 @@ export const useClientTrade = (variables: UseTradeParams) => { ], queryFn: async () => { if ( - !poolsCodeMap || - !isRouteProcessor4ChainId(chainId) || - !fromToken || - !amount || - !toToken || - !gasPrice - ) - return { - abi: undefined, - address: undefined, - swapPrice: undefined, - priceImpact: undefined, - amountIn: undefined, - amountOut: undefined, - minAmountOut: undefined, - gasSpent: undefined, - // writeArgs: undefined, - route: undefined, - // functionName: 'processRoute', - value: undefined, - tokenTax: undefined, - } + poolsCodeMap && + isRouteProcessor5ChainId(chainId) && + fromToken && + amount && + toToken && + gasPrice + ) { + const route = Router.findSpecialRoute( + poolsCodeMap, + chainId, + fromToken, + amount.quotient, + toToken, + Number(gasPrice), + 1, // 5% impact before dex aggregation + ) - const route = Router.findSpecialRoute( - poolsCodeMap, - chainId, - fromToken, - amount.quotient, - toToken, - Number(gasPrice), - 1, // 5% impact before dex aggregation - ) - - let args = undefined - - if (recipient) { - if (isRouteProcessor5ChainId(chainId)) { - args = Router.routeProcessor5Params( - poolsCodeMap, - route, - fromToken, - toToken, - recipient, - ROUTE_PROCESSOR_5_ADDRESS[chainId], - [], - +slippagePercentage / 100, - ) - } else if (isRouteProcessor4ChainId(chainId)) { - args = Router.routeProcessor4Params( - poolsCodeMap, - route, - fromToken, - toToken, - recipient, - ROUTE_PROCESSOR_4_ADDRESS[chainId], - [], - +slippagePercentage / 100, - ) - } - } + const maxSlippage = +slippagePercentage / 100 + + const chargeFee = + !isWrapOrUnwrap({ fromToken, toToken }) && + !isStable({ fromToken, toToken }) && + !isLsd({ fromToken, toToken }) + + const minAmountOut = Amount.fromRawAmount( + toToken, + (route.amountOutBI * getBigInt((1 - maxSlippage) * 1_000_000)) / + 1_000_000n, + ) + + const args = recipient + ? Router.routeProcessor5Params( + poolsCodeMap, + route, + fromToken, + toToken, + recipient, + ROUTE_PROCESSOR_5_ADDRESS[chainId], + [], + maxSlippage, + RouterLiquiditySource.Sender, + chargeFee + ? ProcessFunction.ProcessRouteWithTransferValueOutput + : ProcessFunction.ProcessRoute, + chargeFee + ? isMultisigChainId(chainId) + ? MULTISIG_ADDRESS[chainId] + : '0xFF64C2d5e23e9c48e8b42a23dc70055EEC9ea098' + : undefined, + chargeFee ? calculateFee(minAmountOut) : undefined, + ) + : undefined - if (route) { const amountIn = Amount.fromRawAmount(fromToken, route.amountInBI) const amountOut = Amount.fromRawAmount( toToken, @@ -141,32 +146,8 @@ export const useClientTrade = (variables: UseTradeParams) => { tokenTax ? new Percent(1).subtract(tokenTax) : 1, ).quotient, ) - const minAmountOut = args?.amountOutMin - ? Amount.fromRawAmount(toToken, args.amountOutMin) - : Amount.fromRawAmount( - toToken, - slippageAmount( - Amount.fromRawAmount(toToken, route.amountOutBI), - new Percent(Math.floor(+slippagePercentage * 100), 10_000), - )[0], - ) - // const isOffset = chainId === ChainId.POLYGON && carbonOffset - // // let writeArgs: UseTradeReturnWriteArgs = args - // let writeArgs: UseTradeReturnWriteArgs = args - // ? [ - // args.tokenIn as Address, - // args.amountIn, - // args.tokenOut as Address, - // args.amountOutMin, - // args.to as Address, - // args.routeCode as Hex, - // ] - // : undefined - - // // const overrides = fromToken.isNative && writeArgs?.[1] ? { value: BigNumber.from(writeArgs?.[1]) } : undefined - // let value = - // fromToken.isNative && writeArgs?.[1] ? writeArgs[1] : undefined + // const isOffset = chainId === ChainId.POLYGON && carbonOffset // if (writeArgs && isOffset && chainId === ChainId.POLYGON) { // writeArgs = [ @@ -180,55 +161,65 @@ export const useClientTrade = (variables: UseTradeParams) => { const value = fromToken.isNative && args?.amountIn ? args.amountIn : undefined - // console.log({ writeArgs }) - - return new Promise((res) => - setTimeout( - () => - res({ - swapPrice: amountOut.greaterThan(0n) - ? new Price({ - baseAmount: amount, - quoteAmount: amountOut, - }) - : undefined, - priceImpact: route.priceImpact - ? new Percent( - BigInt(Math.round(route.priceImpact * 10000)), - 10000n, - ) - : new Percent(0), - amountIn, - amountOut, - minAmountOut, - gasSpent: - price && gasPrice - ? Amount.fromRawAmount( - Native.onChain(chainId), - gasPrice * BigInt(route.gasSpent * 1.2), - ).toSignificant(4) - : undefined, - // gasSpentUsd: - // price && feeData.gasPrice - // ? Amount.fromRawAmount( - // Native.onChain(chainId), - // JSBI.multiply(JSBI.BigInt(feeData.gasPrice), JSBI.BigInt(route.gasSpent * 1.2)) - // ) - // .multiply(price.asFraction) - // .toSignificant(4) - // : undefined, - route, - // functionName: isOffset - // ? 'transferValueAndprocessRoute' - // : 'processRoute', - // writeArgs, + const gasSpent = gasPrice + ? Amount.fromRawAmount( + Native.onChain(chainId), + gasPrice * BigInt(route.gasSpent * 1.2), + ) + : undefined + + return { + swapPrice: amountOut.greaterThan(0n) + ? new Price({ + baseAmount: amount, + quoteAmount: amountOut, + }) + : undefined, + priceImpact: route.priceImpact + ? new Percent(Math.round(route.priceImpact * 10000), 10000) + : new Percent(0), + amountIn, + amountOut, + minAmountOut, + gasSpent: gasSpent?.toSignificant(4), + gasSpentUsd: + price && gasSpent + ? gasSpent.multiply(price.asFraction).toSignificant(4) + : undefined, + fee: + !isWrapOrUnwrap({ fromToken, toToken }) && + !isStable({ fromToken, toToken }) && + !isLsd({ fromToken, toToken }) + ? `${tokenOutPrice ? '$' : ''}${minAmountOut + .multiply(new Percent(25, 10000)) + .multiply(tokenOutPrice ? tokenOutPrice.asFraction : 1) + .toSignificant(4)} ${!tokenOutPrice ? toToken.symbol : ''}` + : '$0', + route, + tx: args + ? { + from: recipient, + to: ROUTE_PROCESSOR_5_ADDRESS[chainId], + data: args?.data, value, - txdata: args?.data, - tokenTax, - }), - 250, - ), - ) + } + : undefined, + tokenTax, + } + } + + return { + swapPrice: undefined, + priceImpact: undefined, + amountIn: undefined, + amountOut: undefined, + minAmountOut: undefined, + gasSpent: undefined, + gasSpentUsd: undefined, + fee: undefined, + route: undefined, + tx: undefined, + tokenTax: undefined, } }, refetchInterval: 10000, diff --git a/apps/web/src/ui/swap/cross-chain/cross-chain-swap-widget.tsx b/apps/web/src/ui/swap/cross-chain/cross-chain-swap-widget.tsx index 20ddf65f9e..002cb09f87 100644 --- a/apps/web/src/ui/swap/cross-chain/cross-chain-swap-widget.tsx +++ b/apps/web/src/ui/swap/cross-chain/cross-chain-swap-widget.tsx @@ -19,7 +19,7 @@ export const CrossChainSwapWidget = () => {
    - + {/* */}
    diff --git a/apps/web/src/ui/swap/simple/simple-swap-settings-overlay.tsx b/apps/web/src/ui/swap/simple/simple-swap-settings-overlay.tsx index 4064f223ac..c155707f37 100644 --- a/apps/web/src/ui/swap/simple/simple-swap-settings-overlay.tsx +++ b/apps/web/src/ui/swap/simple/simple-swap-settings-overlay.tsx @@ -6,7 +6,10 @@ import { SwapApi } from './swap-api-setting' export const SimpleSwapSettingsOverlay = () => { return ( ) diff --git a/apps/web/src/ui/swap/simple/simple-swap-trade-review-dialog.tsx b/apps/web/src/ui/swap/simple/simple-swap-trade-review-dialog.tsx index 2172d16b2a..3c670cd574 100644 --- a/apps/web/src/ui/swap/simple/simple-swap-trade-review-dialog.tsx +++ b/apps/web/src/ui/swap/simple/simple-swap-trade-review-dialog.tsx @@ -193,6 +193,7 @@ export const SimpleSwapTradeReviewDialog: FC<{ from: receipt.from, chain_id: chainId, route: stringify(trade?.route), + tx: stringify(trade?.tx), }) if ( trade?.route?.legs?.every( @@ -207,6 +208,7 @@ export const SimpleSwapTradeReviewDialog: FC<{ txHash: hash, exporerLink: Chain.txUrl(chainId, hash), route: stringify(trade?.route), + tx: stringify(trade?.tx), }) } else if ( trade?.route?.legs?.some( @@ -227,6 +229,7 @@ export const SimpleSwapTradeReviewDialog: FC<{ txHash: hash, exporerLink: Chain.txUrl(chainId, hash), route: stringify(trade?.route), + tx: stringify(trade?.tx), }) } else if ( trade?.route?.legs?.every( @@ -241,6 +244,7 @@ export const SimpleSwapTradeReviewDialog: FC<{ txHash: hash, exporerLink: Chain.txUrl(chainId, hash), route: stringify(trade?.route), + tx: stringify(trade?.tx), }) } else { log.info('unknown', { @@ -248,7 +252,7 @@ export const SimpleSwapTradeReviewDialog: FC<{ txHash: hash, exporerLink: Chain.txUrl(chainId, hash), route: stringify(trade?.route), - txdata: stringify(trade?.txdata), + tx: stringify(trade?.tx), }) } } else { @@ -257,6 +261,7 @@ export const SimpleSwapTradeReviewDialog: FC<{ from: receipt.from, chain_id: chainId, route: stringify(trade?.route), + tx: stringify(trade?.tx), }) if ( trade?.route?.legs?.every( @@ -270,6 +275,7 @@ export const SimpleSwapTradeReviewDialog: FC<{ chainId: chainId, txHash: hash, route: stringify(trade?.route), + tx: stringify(trade?.tx), }) } else if ( trade?.route?.legs?.some( @@ -289,6 +295,7 @@ export const SimpleSwapTradeReviewDialog: FC<{ chainId: chainId, txHash: hash, route: stringify(trade?.route), + tx: stringify(trade?.tx), }) } else if ( trade?.route?.legs?.every( @@ -302,13 +309,14 @@ export const SimpleSwapTradeReviewDialog: FC<{ chainId: chainId, txHash: hash, route: stringify(trade?.route), + tx: stringify(trade?.tx), }) } else { log.error('unknown', { chainId: chainId, txHash: hash, route: stringify(trade?.route), - txdata: stringify(trade?.txdata), + tx: stringify(trade?.tx), }) } } @@ -339,18 +347,18 @@ export const SimpleSwapTradeReviewDialog: FC<{ sendAnalyticsEvent(SwapEventName.SWAP_ERROR, { route: stringify(trade?.route), - data: stringify(trade?.txdata), + tx: stringify(trade?.tx), error: e instanceof Error ? e.message : undefined, }) log.error('swap error', { route: stringify(trade?.route), - data: stringify(trade?.txdata), + tx: stringify(trade?.tx), error: stringify(e), }) createErrorToast(e.message, false) }, - [trade?.route, trade?.txdata], + [trade?.route, trade?.tx], ) const { diff --git a/apps/web/src/ui/swap/simple/simple-swap-widget.tsx b/apps/web/src/ui/swap/simple/simple-swap-widget.tsx index e8eb107876..ff006800bb 100644 --- a/apps/web/src/ui/swap/simple/simple-swap-widget.tsx +++ b/apps/web/src/ui/swap/simple/simple-swap-widget.tsx @@ -21,7 +21,7 @@ export const SimpleSwapWidget = () => {
    - + {/* */}
    diff --git a/packages/react-query/src/hooks/trade/types.ts b/packages/react-query/src/hooks/trade/types.ts index c019721b3f..67fbd5f9b6 100644 --- a/packages/react-query/src/hooks/trade/types.ts +++ b/packages/react-query/src/hooks/trade/types.ts @@ -39,12 +39,16 @@ export interface UseTradeReturn { minAmountOut: Amount | undefined gasSpent: string | undefined gasSpentUsd: string | undefined - // functionName: 'processRoute' | 'transferValueAndprocessRoute' - // writeArgs: UseTradeReturnWriteArgs route: TradeType['route'] - value?: bigint | undefined + tx: + | { + from: Address + to: Address + data: string + value: bigint | undefined + } + | undefined tokenTax: Percent | false | undefined - txdata: string | undefined fee: string | undefined } diff --git a/packages/react-query/src/hooks/trade/useTrade.ts b/packages/react-query/src/hooks/trade/useTrade.ts index 6708c1906e..a49cfc82b3 100644 --- a/packages/react-query/src/hooks/trade/useTrade.ts +++ b/packages/react-query/src/hooks/trade/useTrade.ts @@ -9,6 +9,7 @@ import { slippageAmount } from 'sushi/calculate' import { ChainId } from 'sushi/chain' import { MULTISIG_ADDRESS, + ROUTE_PROCESSOR_5_ADDRESS, isMultisigChainId, isRouteProcessor4ChainId, isRouteProcessor5ChainId, @@ -17,7 +18,7 @@ import { import { Amount, Native, Price, type Type } from 'sushi/currency' import { Fraction, Percent, ZERO } from 'sushi/math' import { isLsd, isStable, isWrapOrUnwrap } from 'sushi/router' -import { stringify, zeroAddress } from 'viem' +import { Address, stringify, zeroAddress } from 'viem' import { usePrice } from '../prices' import { apiAdapter02To01 } from './apiAdapter' import type { UseTradeParams, UseTradeQuerySelect } from './types' @@ -151,6 +152,12 @@ export const useTrade = (variables: UseTradeParams) => { enabled: isWNativeSupported(chainId), }) + const price = useMemo(() => { + return Native.onChain(chainId).wrapped.address === zeroAddress + ? new Fraction(0) + : _price + }, [_price, chainId]) + // const { data: tokenInPrice } = usePrice({ // chainId, // address: fromToken?.wrapped.address, @@ -161,15 +168,16 @@ export const useTrade = (variables: UseTradeParams) => { address: toToken?.wrapped.address, }) - const price = useMemo(() => { - return Native.onChain(chainId).wrapped.address === zeroAddress - ? new Fraction(0) - : _price - }, [_price, chainId]) - const select: UseTradeQuerySelect = useCallback( (data) => { - if (data && amount && data.route && fromToken && toToken) { + if ( + isRouteProcessor5ChainId(chainId) && + data && + amount && + data.route && + fromToken && + toToken + ) { const amountIn = Amount.fromRawAmount(fromToken, data.route.amountInBI) const amountOut = Amount.fromRawAmount( toToken, @@ -189,20 +197,6 @@ export const useTrade = (variables: UseTradeParams) => { // const isOffset = chainId === ChainId.POLYGON && carbonOffset - // let writeArgs: UseTradeReturnWriteArgs = data?.args - // ? ([ - // data.args.tokenIn as Address, - // data.args.amountIn, - // data.args.tokenOut as Address, - // data.args.amountOutMin, - // data.args.to as Address, - // data.args.routeCode as Hex, - // ] as const) - // : undefined - // let value = fromToken.isNative ? writeArgs?.[1] ?? undefined : undefined - - const value = fromToken.isNative ? data?.args?.amountIn : undefined - // if (writeArgs && isOffset && chainId === ChainId.POLYGON) { // writeArgs = [ // '0xbc4a6be1285893630d45c881c6c343a65fdbe278', @@ -212,6 +206,8 @@ export const useTrade = (variables: UseTradeParams) => { // value = (fromToken.isNative ? writeArgs[3] : 0n) + 20000000000000000n // } + const value = fromToken.isNative ? data?.args?.amountIn : undefined + const gasSpent = gasPrice ? Amount.fromRawAmount( Native.onChain(chainId), @@ -247,13 +243,16 @@ export const useTrade = (variables: UseTradeParams) => { .toSignificant(4)} ${!tokenOutPrice ? toToken.symbol : ''}` : '$0', route: data.route, - // functionName: isOffset - // ? 'transferValueAndprocessRoute' - // : 'processRoute', - // writeArgs, - value, + tx: + data?.args && data?.txdata + ? { + from: data.args.to as Address, + to: ROUTE_PROCESSOR_5_ADDRESS[chainId], + data: data.txdata, + value, + } + : undefined, tokenTax, - txdata: data.txdata, } } @@ -266,12 +265,9 @@ export const useTrade = (variables: UseTradeParams) => { gasSpent: undefined, gasSpentUsd: undefined, fee: undefined, - // writeArgs: undefined, route: undefined, - // functionName: 'processRoute', - value: undefined, + tx: undefined, tokenTax: undefined, - txdata: undefined, } }, [ diff --git a/packages/sushi/src/config/route-processor.ts b/packages/sushi/src/config/route-processor.ts index 041149ccfa..115730950a 100644 --- a/packages/sushi/src/config/route-processor.ts +++ b/packages/sushi/src/config/route-processor.ts @@ -1,3 +1,4 @@ +import type { Address } from 'viem' import { ChainId } from '../chain/index.js' // v1 @@ -382,7 +383,7 @@ export type RouteProcessor5ChainId = (typeof ROUTE_PROCESSOR_5_SUPPORTED_CHAIN_IDS)[number] export const ROUTE_PROCESSOR_5_ADDRESS: Record< RouteProcessor5ChainId, - `0x${string}` + Address > = { [ChainId.ETHEREUM]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', [ChainId.ARBITRUM]: '0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55', diff --git a/packages/sushi/src/router/index.ts b/packages/sushi/src/router/index.ts index 87b30408a0..eb3ff0f52a 100644 --- a/packages/sushi/src/router/index.ts +++ b/packages/sushi/src/router/index.ts @@ -3,7 +3,6 @@ export * from './pool-codes/index.js' export * from './data-fetcher.js' export * from './get-currency-combinations.js' export * from './HEXer.js' -export * from './makeAPI02Object.js' export * from './router.js' export * from './tines-to-route-processor-2.js' export * from './tines-to-route-processor-4.js' From f5c28b8b832cc8417ca93ba463fe4b1408801117 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Wed, 7 Aug 2024 08:31:33 +0100 Subject: [PATCH 071/125] chore: cleanup --- apps/web/src/lib/wagmi/hooks/trade/use-client-trade.ts | 9 +++++---- .../src/ui/swap/cross-chain/cross-chain-swap-widget.tsx | 2 -- apps/web/src/ui/swap/simple/simple-swap-widget.tsx | 2 -- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/apps/web/src/lib/wagmi/hooks/trade/use-client-trade.ts b/apps/web/src/lib/wagmi/hooks/trade/use-client-trade.ts index 383df9dbc2..2a9b067b89 100644 --- a/apps/web/src/lib/wagmi/hooks/trade/use-client-trade.ts +++ b/apps/web/src/lib/wagmi/hooks/trade/use-client-trade.ts @@ -4,10 +4,9 @@ import { usePrice, } from '@sushiswap/react-query' import { UseQueryResult, useQuery } from '@tanstack/react-query' -import { is } from 'date-fns/locale' import { useMemo } from 'react' import { getBigInt } from 'sushi' -import { calculateFee, slippageAmount } from 'sushi/calculate' +import { calculateFee } from 'sushi/calculate' import { MULTISIG_ADDRESS, ROUTE_PROCESSOR_5_ADDRESS, @@ -29,7 +28,9 @@ import { zeroAddress } from 'viem' import { useGasPrice } from 'wagmi' import { usePoolsCodeMap } from '../pools/hooks/usePoolsCodeMap' -export const useClientTrade = (variables: UseTradeParams) => { +export const useClientTrade = ( + variables: UseTradeParams, +): UseQueryResult => { const { chainId, fromToken, @@ -226,5 +227,5 @@ export const useClientTrade = (variables: UseTradeParams) => { enabled: Boolean( enabled && poolsCodeMap && gasPrice && fromToken && toToken && chainId, ), - }) as UseQueryResult + }) } diff --git a/apps/web/src/ui/swap/cross-chain/cross-chain-swap-widget.tsx b/apps/web/src/ui/swap/cross-chain/cross-chain-swap-widget.tsx index 002cb09f87..81e4f36086 100644 --- a/apps/web/src/ui/swap/cross-chain/cross-chain-swap-widget.tsx +++ b/apps/web/src/ui/swap/cross-chain/cross-chain-swap-widget.tsx @@ -1,4 +1,3 @@ -import { CrossChainBanner } from '../cross-chain-banner' import { SwapModeButtons } from '../swap-mode-buttons' import { CrossChainSwapHeader } from './cross-chain-swap-header' import { CrossChainSwapMaintenanceMessage } from './cross-chain-swap-maintenance-message' @@ -19,7 +18,6 @@ export const CrossChainSwapWidget = () => {
    - {/* */}
    diff --git a/apps/web/src/ui/swap/simple/simple-swap-widget.tsx b/apps/web/src/ui/swap/simple/simple-swap-widget.tsx index ff006800bb..cb2fb0210f 100644 --- a/apps/web/src/ui/swap/simple/simple-swap-widget.tsx +++ b/apps/web/src/ui/swap/simple/simple-swap-widget.tsx @@ -1,4 +1,3 @@ -import { CrossChainBanner } from '../cross-chain-banner' import { SwapModeButtons } from '../swap-mode-buttons' import { SimpleSwapBridgeBanner } from './simple-swap-bridge-banner' import { SimpleSwapHeader } from './simple-swap-header' @@ -21,7 +20,6 @@ export const SimpleSwapWidget = () => {
    - {/* */}
    From 642689587a6a15ece47fc2ea572a1b07f6c766cd Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Wed, 7 Aug 2024 13:06:19 +0100 Subject: [PATCH 072/125] chore: v5 swap api improvements --- apis/router/src/create-swap-body.ts | 185 ++++++++++++++++++ apis/router/src/handlers/swap/index.ts | 31 +-- apis/router/src/handlers/swap2/index.ts | 80 ++++---- apis/router/src/handlers/swap2/schema.ts | 28 +-- apis/router/src/index.ts | 3 + apis/router/src/make-api-object.ts | 152 -------------- .../lib/wagmi/hooks/trade/use-client-trade.ts | 6 +- .../simple/simple-swap-settings-overlay.tsx | 2 + .../react-query/src/hooks/trade/apiAdapter.ts | 38 ++-- packages/react-query/src/hooks/trade/types.ts | 10 +- .../react-query/src/hooks/trade/useTrade.ts | 35 ++-- .../src/hooks/trade/validator01.ts | 16 ++ .../src/hooks/trade/validator02.ts | 19 +- packages/ui/src/components/settings/index.tsx | 1 - 14 files changed, 350 insertions(+), 256 deletions(-) create mode 100644 apis/router/src/create-swap-body.ts delete mode 100644 apis/router/src/make-api-object.ts diff --git a/apis/router/src/create-swap-body.ts b/apis/router/src/create-swap-body.ts new file mode 100644 index 0000000000..4e08ed8ba4 --- /dev/null +++ b/apis/router/src/create-swap-body.ts @@ -0,0 +1,185 @@ +import type { LiquidityProviders, RPParams } from 'sushi/router' +import { + type MultiRoute, + type RToken, + type RouteLeg, + RouteStatus, +} from 'sushi/tines' + +function makeAPI02Token(token: RToken) { + return { + address: token.address || '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE', + symbol: token.symbol, + name: token.name, + decimals: token.decimals, + } +} + +function makeAPI02Leg(leg: RouteLeg, tokens: TokenConvertor) { + return { + poolAddress: leg.poolAddress, + poolType: leg.poolType, + // @ts-ignore + poolName: leg.poolName as string, // Don't know how, but it exists. Too long to recreate it from poolCodes + poolFee: leg.poolFee, + // @ts-ignore + liquidityProvider: leg.liquidityProvider as LiquidityProviders, + tokenFrom: tokens.getTokenIndex(leg.tokenFrom), + tokenTo: tokens.getTokenIndex(leg.tokenTo), + share: leg.absolutePortion, + assumedAmountIn: BigInt(leg.assumedAmountIn).toString(), + assumedAmountOut: BigInt(leg.assumedAmountOut).toString(), + } +} + +class TokenConvertor { + tokens: RToken[] = [] + tokenMap = new Map() + + _tokenId(t: RToken) { + return t.tokenId ?? t.symbol + } + + addToken(t: RToken) { + if (this.tokenMap.get(this._tokenId(t)) === undefined) { + this.tokens.push(makeAPI02Token(t)) + this.tokenMap.set(this._tokenId(t), this.tokens.length - 1) + } + } + + getTokenIndex(t: RToken) { + return this.tokenMap.get(this._tokenId(t)) + } + + getTokenList() { + return this.tokens + } +} + +// export function makeAPI02Object( +// route: MultiRoute, +// rpParams: RPParams | undefined, +// routeProcessorAddr: string, +// ) { +// if (route.status === RouteStatus.NoWay) return { status: RouteStatus.NoWay } +// const tokens = new TokenConvertor() +// route.legs.forEach((l) => { +// tokens.addToken(l.tokenFrom) +// tokens.addToken(l.tokenTo) +// }) +// const APIObj = { +// status: route.status, +// tokens: tokens.getTokenList(), +// tokenFrom: tokens.getTokenIndex(route.fromToken), +// tokenTo: tokens.getTokenIndex(route.toToken), + +// primaryPrice: route.primaryPrice, +// swapPrice: route.swapPrice, +// priceImpact: route.priceImpact, + +// amountIn: route.amountInBI.toString(), +// assumedAmountOut: route.amountOutBI.toString(), +// gasSpent: route.gasSpent, + +// route: route.legs.map((l) => makeAPI02Leg(l, tokens)), +// } as any +// if (rpParams !== undefined) { +// APIObj.routeProcessorAddr = routeProcessorAddr +// APIObj.routeProcessorArgs = { +// tokenIn: rpParams.tokenIn, +// amountIn: rpParams.amountIn.toString(), +// tokenOut: rpParams.tokenOut, +// amountOutMin: rpParams.amountOutMin.toString(), +// to: rpParams.to, +// routeCode: rpParams.routeCode, +// txdata: rpParams.data, +// } +// if (rpParams.value !== undefined) +// APIObj.routeProcessorArgs.value = rpParams.value.toString() +// } + +// return APIObj +// } + +export function createSwapBody( + route: MultiRoute, + rpParams?: RPParams | undefined, + routeProcessorAddress?: string | undefined, + includeRouteProcessorParams?: boolean, + includeTransaction?: boolean, + includeRoute?: boolean, + debug?: boolean, +) { + if (route.status === RouteStatus.NoWay) return { status: RouteStatus.NoWay } + const tokens = new TokenConvertor() + route.legs.forEach((l) => { + tokens.addToken(l.tokenFrom) + tokens.addToken(l.tokenTo) + }) + + const _debug = typeof debug === 'boolean' && debug + const _includeRouteProcessorParams = + typeof includeRouteProcessorParams === 'boolean' && + includeRouteProcessorParams + const _includeTransaction = + typeof includeTransaction === 'boolean' && includeTransaction + const _includeRoute = typeof includeRoute === 'boolean' && includeRoute + + return { + status: route.status, + tokens: tokens.getTokenList(), + tokenFrom: tokens.getTokenIndex(route.fromToken), + tokenTo: tokens.getTokenIndex(route.toToken), + + primaryPrice: _debug ? route.primaryPrice : undefined, + swapPrice: route.swapPrice, + priceImpact: route.priceImpact, + + amountIn: route.amountInBI.toString(), + assumedAmountOut: route.amountOutBI.toString(), + gasSpent: route.gasSpent, + + route: _includeRoute + ? route.legs.map((l) => makeAPI02Leg(l, tokens)) + : undefined, + + // we want to return { route, tx: { from, to, gas, gasPrice, data, value, } } + + // for backwards compatibility in the meantime + routeProcessorAddr: + routeProcessorAddress !== undefined ? routeProcessorAddress : undefined, + routeProcessorArgs: + _includeRouteProcessorParams && rpParams !== undefined + ? { + tokenIn: rpParams.tokenIn, + amountIn: rpParams.amountIn.toString(), + tokenOut: rpParams.tokenOut, + amountOutMin: rpParams.amountOutMin.toString(), + to: rpParams.to, + routeCode: rpParams.routeCode, + txdata: rpParams.data, + value: + rpParams.value !== undefined + ? rpParams.value.toString() + : undefined, + } + : undefined, + + tx: + _includeTransaction && rpParams !== undefined + ? { + from: rpParams.to, + to: routeProcessorAddress, + // we could include a simulation of gas usage + // gas: rpParams.gas, + // we could include a gas price estimatation + // gasPrice: rpParams.gasPrice, + data: rpParams.data, + value: + rpParams.value !== undefined + ? rpParams.value.toString() + : undefined, + } + : undefined, + } +} diff --git a/apis/router/src/handlers/swap/index.ts b/apis/router/src/handlers/swap/index.ts index d728b75a3e..37713b2e35 100644 --- a/apis/router/src/handlers/swap/index.ts +++ b/apis/router/src/handlers/swap/index.ts @@ -21,7 +21,7 @@ import { MAX_TIME_WITHOUT_NETWORK_UPDATE, POOL_FETCH_TIMEOUT, } from '../../config.js' -import { makeAPI02Object } from '../../make-api-object.js' +import { createSwapBody } from '../../create-swap-body.js' import { querySchema3_2 } from './schema.js' const nativeProvider = new NativeWrapProvider( @@ -43,21 +43,21 @@ async function processUnknownToken( } function handler( - qSchema: typeof querySchema3_2, - rpCode: typeof Router.routeProcessor3_2Params, - rpAddress: Address, + querySchema: typeof querySchema3_2, + routeProcessorParams: typeof Router.routeProcessor3_2Params, + routeProcessorAddress: Address, ) { return (client: ExtractorClient) => { return async (req: Request, res: Response) => { res.setHeader('Cache-Control', 's-maxage=2, stale-while-revalidate=28') let parsedData: any = undefined - let bestRoute: MultiRoute | undefined = undefined + let route: MultiRoute | undefined = undefined try { const statistics = swapRequestStatistics.requestProcessingStart() let parsed: ReturnType | undefined try { - parsed = qSchema.safeParse(req.query) + parsed = querySchema.safeParse(req.query) } catch (_e) {} if (!parsed || !parsed.success) { swapRequestStatistics.requestRejected( @@ -131,7 +131,7 @@ function handler( .getCurrentPoolList() .forEach((p) => poolCodesMap.set(p.pool.uniqueID(), p)) - bestRoute = preferSushi + route = preferSushi ? Router.findSpecialRoute( poolCodesMap, CHAIN_ID as ChainId, @@ -149,28 +149,29 @@ function handler( gasPrice ?? 30e9, ) - const json = makeAPI02Object( - bestRoute, + const body = createSwapBody( + route, to - ? rpCode( + ? routeProcessorParams( poolCodesMap, - bestRoute, + route, tokenIn, tokenOut, to, - rpAddress as Address, + routeProcessorAddress as Address, [], maxPriceImpact, source ?? RouterLiquiditySource.Sender, ) : undefined, - rpAddress as Address, + routeProcessorAddress, + true, ) // we want to return { route, tx: { from, to, gas, gasPrice, value, input } } swapRequestStatistics.requestWasProcessed(statistics, tokensAreKnown) - return res.json(json) + return res.json(body) } catch (e) { swapRequestStatistics.requestRejected( ResponseRejectReason.UNKNOWN_EXCEPTION, @@ -180,7 +181,7 @@ function handler( try { data.error = e instanceof Error ? e.stack?.split('\n') : `${e}` if (parsedData) data.params = parsedData - if (bestRoute) data.route = makeAPI02Object(bestRoute, undefined, '') + if (route) data.route = createSwapBody(route) } catch (_e) {} Logger.error(CHAIN_ID, 'Routing crashed', safeSerialize(data), false) diff --git a/apis/router/src/handlers/swap2/index.ts b/apis/router/src/handlers/swap2/index.ts index cb3d28142b..6b144f4368 100644 --- a/apis/router/src/handlers/swap2/index.ts +++ b/apis/router/src/handlers/swap2/index.ts @@ -26,7 +26,7 @@ import { MAX_TIME_WITHOUT_NETWORK_UPDATE, POOL_FETCH_TIMEOUT, } from '../../config.js' -import { makeAPI02Object } from '../../make-api-object.js' +import { createSwapBody } from '../../create-swap-body.js' // import { swapResponse } from './response.js' import { querySchema5 } from './schema.js' @@ -58,7 +58,7 @@ const handler = ( res.setHeader('Cache-Control', 's-maxage=2, stale-while-revalidate=28') let poolCodesMap: Map = new Map() - let bestRoute: MultiRoute | undefined = undefined + let route: MultiRoute | undefined = undefined let amountValueTransfer: bigint | undefined = undefined let processFunction = ProcessFunction.ProcessRoute @@ -86,8 +86,12 @@ const handler = ( maxSlippage, enableFee, feeReceiver, - feeAmount, - chargeFeeBy, + fee, + feeBy, + includeTransaction, + includeRouteProcessorParams, + includeRoute, + debug, } = parsed.data if ( client.lastUpdatedTimestamp + MAX_TIME_WITHOUT_NETWORK_UPDATE < @@ -136,18 +140,18 @@ const handler = ( !isStable({ fromToken: tokenIn, toToken: tokenOut }) && !isLsd({ fromToken: tokenIn, toToken: tokenOut }) - if (chargeFee && chargeFeeBy === TransferValue.Input) { + if (chargeFee && feeBy === TransferValue.Input) { processFunction = ProcessFunction.ProcessRouteWithTransferValueInput amountValueTransfer = - (_amount * getBigInt(feeAmount * 1_000_000)) / 1_000_000n + (_amount * getBigInt(fee * 1_000_000)) / 1_000_000n } const amount = - chargeFeeBy === TransferValue.Input && amountValueTransfer + feeBy === TransferValue.Input && amountValueTransfer ? _amount - amountValueTransfer : _amount - bestRoute = preferSushi + route = preferSushi ? Router.findSpecialRoute( poolCodesMap, CHAIN_ID, @@ -168,47 +172,53 @@ const handler = ( if ( // If price impact is missing from the route we return no way multiroute - bestRoute.priceImpact === undefined || + route.priceImpact === undefined || (maxPriceImpact !== undefined && // or if max price impact is defined and less than best route price impact we return no way multiroute (not a feature we use at UI) - bestRoute.priceImpact > maxPriceImpact) + route.priceImpact > maxPriceImpact) ) - bestRoute = Router.NoWayMultiRoute(tokenIn, tokenOut) + route = Router.NoWayMultiRoute(tokenIn, tokenOut) const minAmountOut = - (bestRoute.amountOutBI * getBigInt((1 - maxSlippage) * 1_000_000)) / + (route.amountOutBI * getBigInt((1 - maxSlippage) * 1_000_000)) / 1_000_000n - if (chargeFee && chargeFeeBy === TransferValue.Output) { + if (chargeFee && feeBy === TransferValue.Output) { processFunction = ProcessFunction.ProcessRouteWithTransferValueOutput amountValueTransfer = - (minAmountOut * getBigInt(feeAmount * 1_000_000)) / 1_000_000n + (minAmountOut * getBigInt(fee * 1_000_000)) / 1_000_000n } - const rpParams = to - ? routeProcessorParams( - poolCodesMap, - bestRoute, - tokenIn, - tokenOut, - to, - routeProcessorAddress, - [], - maxSlippage, // probably just pass min amount out through instead? - source ?? RouterLiquiditySource.Sender, - processFunction, - feeReceiver, - amountValueTransfer, - ) - : undefined - - const json = makeAPI02Object(bestRoute, rpParams, routeProcessorAddress) + const body = createSwapBody( + route, + to + ? routeProcessorParams( + poolCodesMap, + route, + tokenIn, + tokenOut, + to, + routeProcessorAddress, + [], + maxSlippage, // probably just pass min amount out through instead? + source ?? RouterLiquiditySource.Sender, + processFunction, + feeReceiver, + amountValueTransfer, + ) + : undefined, + routeProcessorAddress, + includeRouteProcessorParams, + includeTransaction, + includeRoute, + debug, + ) // return swapResponse() swapRequestStatistics.requestWasProcessed(statistics, tokensAreKnown) - return res.json(json) + return res.json(body) } catch (e) { swapRequestStatistics.requestRejected( ResponseRejectReason.UNKNOWN_EXCEPTION, @@ -217,7 +227,7 @@ const handler = ( const data: { error: string | string[] | undefined params: z.infer | undefined - route: ReturnType | undefined + route: ReturnType | undefined } = { error: undefined, params: undefined, @@ -226,7 +236,7 @@ const handler = ( try { data.error = e instanceof Error ? e.stack?.split('\n') : `${e}` if (parsed.data) data.params = parsed.data - if (bestRoute) data.route = makeAPI02Object(bestRoute, undefined, '') + if (route) data.route = createSwapBody(route) } catch (_e) {} Logger.error(CHAIN_ID, 'Routing crashed', safeSerialize(data), false) diff --git a/apis/router/src/handlers/swap2/schema.ts b/apis/router/src/handlers/swap2/schema.ts index 08b11fcad8..cbb7fe2445 100644 --- a/apis/router/src/handlers/swap2/schema.ts +++ b/apis/router/src/handlers/swap2/schema.ts @@ -44,17 +44,12 @@ export const querySchema5 = z.object({ .lt(1, 'maxSlippage should be lesser than 1') .positive() .default(0.005), - // includeRoute: z.boolean().default(true), - // includeRpArgs: z.boolean().default(true), - // includeTx: z.boolean().default(true), - enableFee: z.coerce.boolean().default(true), - feeReceiver: z.optional( - z.custom
    ( - (val) => isAddressFast(val), - (val) => ({ message: `Incorrect fee receiver address: ${val}` }), - ), - ), - feeAmount: z + includeRouteProcessorParams: z.optional(z.coerce.boolean()).default(false), + includeTransaction: z.optional(z.coerce.boolean()).default(false), + includeTokens: z.optional(z.coerce.boolean()).default(false), + includeRoute: z.optional(z.coerce.boolean()).default(false), + enableFee: z.optional(z.coerce.boolean()).default(true), + fee: z .optional( z.coerce .number() @@ -62,9 +57,14 @@ export const querySchema5 = z.object({ .positive(), ) .default(0.0025), - chargeFeeBy: z - .optional(z.nativeEnum(TransferValue)) - .default(TransferValue.Output), + feeReceiver: z.optional( + z.custom
    ( + (val) => isAddressFast(val), + (val) => ({ message: `Incorrect fee receiver address: ${val}` }), + ), + ), + feeBy: z.optional(z.nativeEnum(TransferValue)).default(TransferValue.Output), + debug: z.optional(z.coerce.boolean()).default(false), }) export type querySchema5 = z.infer diff --git a/apis/router/src/index.ts b/apis/router/src/index.ts index ddbd904b5a..7180d61c75 100644 --- a/apis/router/src/index.ts +++ b/apis/router/src/index.ts @@ -121,6 +121,9 @@ async function start() { app.get(`/swap/v5/${CHAIN_ID}`, (req, res) => { return swapV5(client)(req, res) }) + app.get(`/quote/v5/${CHAIN_ID}`, (req, res) => { + return swapV5(client)(req, res) + }) app.get(`/token/v1/${CHAIN_ID}/:address`, tokenHandler(client)) diff --git a/apis/router/src/make-api-object.ts b/apis/router/src/make-api-object.ts deleted file mode 100644 index 52c9995c69..0000000000 --- a/apis/router/src/make-api-object.ts +++ /dev/null @@ -1,152 +0,0 @@ -import type { LiquidityProviders, RPParams } from 'sushi/router' -import { - type MultiRoute, - type RToken, - type RouteLeg, - RouteStatus, -} from 'sushi/tines' - -function makeAPI02Token(token: RToken) { - return { - address: token.address || '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE', - symbol: token.symbol, - name: token.name, - decimals: token.decimals, - } -} - -function makeAPI02Leg(leg: RouteLeg, tokens: TokenConvertor) { - return { - poolAddress: leg.poolAddress, - poolType: leg.poolType, - // @ts-ignore - poolName: leg.poolName as string, // Don't know how, but it exists. Too long to recreate it from poolCodes - poolFee: leg.poolFee, - // @ts-ignore - liquidityProvider: leg.liquidityProvider as LiquidityProviders, - tokenFrom: tokens.getTokenIndex(leg.tokenFrom), - tokenTo: tokens.getTokenIndex(leg.tokenTo), - share: leg.absolutePortion, - assumedAmountIn: BigInt(leg.assumedAmountIn).toString(), - assumedAmountOut: BigInt(leg.assumedAmountOut).toString(), - } -} - -class TokenConvertor { - tokens: RToken[] = [] - tokenMap = new Map() - - _tokenId(t: RToken) { - return t.tokenId ?? t.symbol - } - - addToken(t: RToken) { - if (this.tokenMap.get(this._tokenId(t)) === undefined) { - this.tokens.push(makeAPI02Token(t)) - this.tokenMap.set(this._tokenId(t), this.tokens.length - 1) - } - } - - getTokenIndex(t: RToken) { - return this.tokenMap.get(this._tokenId(t)) - } - - getTokenList() { - return this.tokens - } -} - -export function makeAPI02Object( - route: MultiRoute, - rpParams: RPParams | undefined, - routeProcessorAddr: string, -) { - if (route.status === RouteStatus.NoWay) return { status: RouteStatus.NoWay } - const tokens = new TokenConvertor() - route.legs.forEach((l) => { - tokens.addToken(l.tokenFrom) - tokens.addToken(l.tokenTo) - }) - const APIObj = { - status: route.status, - tokens: tokens.getTokenList(), - tokenFrom: tokens.getTokenIndex(route.fromToken), - tokenTo: tokens.getTokenIndex(route.toToken), - - primaryPrice: route.primaryPrice, - swapPrice: route.swapPrice, - priceImpact: route.priceImpact, - - amountIn: route.amountInBI.toString(), - assumedAmountOut: route.amountOutBI.toString(), - gasSpent: route.gasSpent, - - route: route.legs.map((l) => makeAPI02Leg(l, tokens)), - } as any - if (rpParams !== undefined) { - APIObj.routeProcessorAddr = routeProcessorAddr - APIObj.routeProcessorArgs = { - tokenIn: rpParams.tokenIn, - amountIn: rpParams.amountIn.toString(), - tokenOut: rpParams.tokenOut, - amountOutMin: rpParams.amountOutMin.toString(), - to: rpParams.to, - routeCode: rpParams.routeCode, - txdata: rpParams.data, - } - if (rpParams.value !== undefined) - APIObj.routeProcessorArgs.value = rpParams.value.toString() - } - - return APIObj -} - -export function makeAPI03Object( - route: MultiRoute, - rpParams: RPParams | undefined, - routeProcessorAddr: string, - debug = false, -) { - if (route.status === RouteStatus.NoWay) return { status: RouteStatus.NoWay } - const tokens = new TokenConvertor() - route.legs.forEach((l) => { - tokens.addToken(l.tokenFrom) - tokens.addToken(l.tokenTo) - }) - - return { - status: route.status, - tokens: tokens.getTokenList(), - tokenFrom: tokens.getTokenIndex(route.fromToken), - tokenTo: tokens.getTokenIndex(route.toToken), - - primaryPrice: debug ? route.primaryPrice : undefined, - swapPrice: route.swapPrice, - priceImpact: route.priceImpact, - - amountIn: route.amountInBI.toString(), - assumedAmountOut: route.amountOutBI.toString(), - gasSpent: route.gasSpent, - - route: route.legs.map((l) => makeAPI02Leg(l, tokens)), - - // we want to return { route, tx: { from, to, gas, gasPrice, data, value, } } - - tx: - rpParams !== undefined - ? { - from: rpParams.to, - to: routeProcessorAddr, - // we could include a simulation of gas usage - // gas: rpParams.gas, - // we could include a gas price estimatation - // gasPrice: rpParams.gasPrice, - data: rpParams.data, - value: - rpParams.value !== undefined - ? rpParams.value.toString() - : undefined, - } - : undefined, - } -} diff --git a/apps/web/src/lib/wagmi/hooks/trade/use-client-trade.ts b/apps/web/src/lib/wagmi/hooks/trade/use-client-trade.ts index 2a9b067b89..bc55cfd510 100644 --- a/apps/web/src/lib/wagmi/hooks/trade/use-client-trade.ts +++ b/apps/web/src/lib/wagmi/hooks/trade/use-client-trade.ts @@ -24,7 +24,7 @@ import { isStable, isWrapOrUnwrap, } from 'sushi/router' -import { zeroAddress } from 'viem' +import { stringify, zeroAddress } from 'viem' import { useGasPrice } from 'wagmi' import { usePoolsCodeMap } from '../pools/hooks/usePoolsCodeMap' @@ -79,9 +79,10 @@ export const useClientTrade = ( currencyB: toToken, amount, slippagePercentage, + gasPrice, recipient, - poolsCodeMap, source, + poolsCodeMap, tokenTax, }, ], @@ -227,5 +228,6 @@ export const useClientTrade = ( enabled: Boolean( enabled && poolsCodeMap && gasPrice && fromToken && toToken && chainId, ), + queryKeyHashFn: stringify, }) } diff --git a/apps/web/src/ui/swap/simple/simple-swap-settings-overlay.tsx b/apps/web/src/ui/swap/simple/simple-swap-settings-overlay.tsx index c155707f37..b18e0272a1 100644 --- a/apps/web/src/ui/swap/simple/simple-swap-settings-overlay.tsx +++ b/apps/web/src/ui/swap/simple/simple-swap-settings-overlay.tsx @@ -8,6 +8,8 @@ export const SimpleSwapSettingsOverlay = () => { | undefined gasSpent: string | undefined gasSpentUsd: string | undefined - route: TradeType['route'] + route: TradeType1['route'] tx: | { from: Address to: Address data: string - value: bigint | undefined + value?: bigint | undefined } | undefined tokenTax: Percent | false | undefined fee: string | undefined } -export type UseTradeQuerySelect = (data: TradeType) => UseTradeReturn -export type TradeType = z.infer +export type UseTradeQuerySelect = (data: TradeType1) => UseTradeReturn +export type TradeType1 = z.infer +export type TradeType2 = z.infer export type TradeLegType = z.infer diff --git a/packages/react-query/src/hooks/trade/useTrade.ts b/packages/react-query/src/hooks/trade/useTrade.ts index a49cfc82b3..ad7cea74bc 100644 --- a/packages/react-query/src/hooks/trade/useTrade.ts +++ b/packages/react-query/src/hooks/trade/useTrade.ts @@ -9,7 +9,6 @@ import { slippageAmount } from 'sushi/calculate' import { ChainId } from 'sushi/chain' import { MULTISIG_ADDRESS, - ROUTE_PROCESSOR_5_ADDRESS, isMultisigChainId, isRouteProcessor4ChainId, isRouteProcessor5ChainId, @@ -58,8 +57,8 @@ export const useTradeQuery = ( 'getTrade', { chainId, - fromToken, - toToken, + currencyA: fromToken, + currencyB: toToken, amount, slippagePercentage, gasPrice, @@ -102,14 +101,16 @@ export const useTradeQuery = ( ? MULTISIG_ADDRESS[chainId] : '0xFF64C2d5e23e9c48e8b42a23dc70055EEC9ea098', ) - params.searchParams.set('feeAmount', '0.0025') - params.searchParams.set('chargeFeeBy', 'output') + params.searchParams.set('fee', '0.0025') + params.searchParams.set('feeBy', 'output') + params.searchParams.set('includeTransaction', 'true') + params.searchParams.set('includeRoute', 'true') if (source !== undefined) params.searchParams.set('source', `${source}`) const res = await fetch(params.toString()) - // const json = deserialize(await res.json()) should cause react query error const json = await res.json() const resp2 = tradeValidator02.parse(json) + const resp1 = apiAdapter02To01( resp2, fromToken as Type, @@ -206,7 +207,10 @@ export const useTrade = (variables: UseTradeParams) => { // value = (fromToken.isNative ? writeArgs[3] : 0n) + 20000000000000000n // } - const value = fromToken.isNative ? data?.args?.amountIn : undefined + // const value = + // fromToken.isNative && data?.args?.amountIn + // ? data.args.amountIn + // : undefined const gasSpent = gasPrice ? Amount.fromRawAmount( @@ -243,15 +247,14 @@ export const useTrade = (variables: UseTradeParams) => { .toSignificant(4)} ${!tokenOutPrice ? toToken.symbol : ''}` : '$0', route: data.route, - tx: - data?.args && data?.txdata - ? { - from: data.args.to as Address, - to: ROUTE_PROCESSOR_5_ADDRESS[chainId], - data: data.txdata, - value, - } - : undefined, + tx: data?.tx + ? { + from: data.tx.from as Address, + to: data.tx.to, + data: data.tx.data, + value: data.tx.value, + } + : undefined, tokenTax, } } diff --git a/packages/react-query/src/hooks/trade/validator01.ts b/packages/react-query/src/hooks/trade/validator01.ts index c6fee0673b..2fe12cd375 100644 --- a/packages/react-query/src/hooks/trade/validator01.ts +++ b/packages/react-query/src/hooks/trade/validator01.ts @@ -1,3 +1,5 @@ +import { isAddressFast } from 'sushi/serializer' +import { Address } from 'viem' import z from 'zod' export const tokenValidator = z.object({ @@ -53,5 +55,19 @@ export const tradeValidator01 = z.object({ routeCode: z.string(), }), ), + tx: z.optional( + z.object({ + from: z.custom
    ( + (val) => isAddressFast(val), + (val) => ({ message: `Incorrect address for 'from': ${val}` }), + ), + to: z.custom
    ( + (val) => isAddressFast(val), + (val) => ({ message: `Incorrect address for 'to': ${val}` }), + ), + data: z.string(), + value: z.coerce.bigint().optional(), + }), + ), txdata: z.optional(z.string()), }) diff --git a/packages/react-query/src/hooks/trade/validator02.ts b/packages/react-query/src/hooks/trade/validator02.ts index 2e937ef3de..a469fbac5c 100644 --- a/packages/react-query/src/hooks/trade/validator02.ts +++ b/packages/react-query/src/hooks/trade/validator02.ts @@ -1,4 +1,6 @@ +import { isAddressFast } from 'sushi/serializer' import { PoolType } from 'sushi/tines' +import { Address } from 'viem' import z from 'zod' export const tokenValidator = z.object({ @@ -26,7 +28,7 @@ const routeExistValidator = z.object({ tokenFrom: z.number(), // index in tokens array tokenTo: z.number(), // index in tokens array - primaryPrice: z.number(), + primaryPrice: z.number().optional(), // only if debug swapPrice: z.number(), priceImpact: z.number(), @@ -49,6 +51,21 @@ const routeExistValidator = z.object({ txdata: z.string(), }) .optional(), + + tx: z.optional( + z.object({ + from: z.custom
    ( + (val) => isAddressFast(val), + (val) => ({ message: `Incorrect address for 'from': ${val}` }), + ), + to: z.custom
    ( + (val) => isAddressFast(val), + (val) => ({ message: `Incorrect address for 'to': ${val}` }), + ), + data: z.string(), + value: z.coerce.bigint().optional(), + }), + ), }) const routeDontExistValidator = z.object({ diff --git a/packages/ui/src/components/settings/index.tsx b/packages/ui/src/components/settings/index.tsx index c734437bd0..ea8acadb10 100644 --- a/packages/ui/src/components/settings/index.tsx +++ b/packages/ui/src/components/settings/index.tsx @@ -66,7 +66,6 @@ export const SettingsOverlay: FC = ({ const [slippageTolerance, setSlippageTolerance] = useSlippageTolerance( options?.slippageTolerance?.storageKey, ) - return ( From 08d95c1f21cfad24b18ee99074dd482aebc4e50a Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Wed, 7 Aug 2024 13:53:21 +0100 Subject: [PATCH 073/125] fix: lint --- apps/web/src/config.ts | 4 +++- apps/web/src/lib/hooks/useSimulateTrade.ts | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/web/src/config.ts b/apps/web/src/config.ts index 4535727277..66c7ae901a 100644 --- a/apps/web/src/config.ts +++ b/apps/web/src/config.ts @@ -46,9 +46,11 @@ const SUSHI_CHAIN_IDS = Array.from( new Set([...TridentChainIds, ...SushiSwapV2ChainIds, ...SushiSwapV3ChainIds]), ) +export const SWAP_ONLY_CHAIN_IDS = [ChainId.CRONOS] as const + export const CHAIN_IDS = [ ...SUSHI_CHAIN_IDS, - // ChainId.CRONOS, + // ChainId.CRONOS ] as const export const SUPPORTED_CHAIN_IDS = Array.from( diff --git a/apps/web/src/lib/hooks/useSimulateTrade.ts b/apps/web/src/lib/hooks/useSimulateTrade.ts index d71e370d72..324cd81e87 100644 --- a/apps/web/src/lib/hooks/useSimulateTrade.ts +++ b/apps/web/src/lib/hooks/useSimulateTrade.ts @@ -116,6 +116,6 @@ export function useSimulateTrade({ ? null : simulateTrade.error, }), - [simulateTrade, trade, chainId, address], + [simulateTrade, trade, address], ) } From 35906910003c85688d9744d24dff7dc7584b202b Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Wed, 7 Aug 2024 14:34:56 +0100 Subject: [PATCH 074/125] chore: regenerate mocks --- .../test/swap/mock/137-native-to-usdc.json | 149 ++++++++++++--- .../test/swap/mock/137-native-to-usdt.json | 121 +++++++++--- .../test/swap/mock/137-native-to-wbtc.json | 152 ++++++++++----- apps/web/test/swap/mock/137-unwrap.json | 25 +-- .../test/swap/mock/137-usdc-to-native.json | 176 +++++++++++++++--- apps/web/test/swap/mock/137-usdc-to-usdt.json | 35 ++-- .../test/swap/mock/137-usdt-to-native.json | 167 ++++++++++++++--- apps/web/test/swap/mock/137-wrap.json | 27 ++- 8 files changed, 655 insertions(+), 197 deletions(-) diff --git a/apps/web/test/swap/mock/137-native-to-usdc.json b/apps/web/test/swap/mock/137-native-to-usdc.json index cd74f7acd9..9a0b7585fb 100644 --- a/apps/web/test/swap/mock/137-native-to-usdc.json +++ b/apps/web/test/swap/mock/137-native-to-usdc.json @@ -18,16 +18,39 @@ "symbol": "USDC", "name": "USD Coin (PoS)", "decimals": 6 + }, + { + "address": "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359", + "symbol": "USDC", + "name": "USD Coin", + "decimals": 6 + }, + { + "address": "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619", + "symbol": "WETH", + "name": "Wrapped Ether", + "decimals": 18 + }, + { + "address": "0xc2132D05D31c914a87C6611C10748AEb04B58e8F", + "symbol": "USDT", + "name": "(PoS) Tether USD", + "decimals": 6 + }, + { + "address": "0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063", + "symbol": "DAI", + "name": "(PoS) Dai Stablecoin", + "decimals": 18 } ], "tokenFrom": 0, - "tokenTo": 2, - "primaryPrice": 8.9256093504231e-13, - "swapPrice": 8.9475609e-13, - "priceImpact": -0.0024593894618365475, + "tokenTo": 3, + "swapPrice": 4.0666556999999975e-13, + "priceImpact": 0.0031127967403997703, "amountIn": "100000000000000000000", - "assumedAmountOut": "89475609", - "gasSpent": 160000, + "assumedAmountOut": "40666557", + "gasSpent": 940000, "route": [ { "poolAddress": "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", @@ -37,8 +60,8 @@ "tokenFrom": 0, "tokenTo": 1, "share": 1, - "assumedAmountIn": "100000000000000000000", - "assumedAmountOut": "100000000000000000000" + "assumedAmountIn": "100000000000000065536", + "assumedAmountOut": "100000000000000065536" }, { "poolAddress": "0x21988C9CFD08db3b5793c2C6782271dC94749251", @@ -47,20 +70,104 @@ "poolFee": 0.0005, "tokenFrom": 1, "tokenTo": 2, + "share": 0.37, + "assumedAmountIn": "37000076295109509120", + "assumedAmountOut": "15073271" + }, + { + "poolAddress": "0x562A0460FE6cfc2E610AE5596c5b4ACe94d97C56", + "poolType": "Concentrated", + "poolName": "SushiSwapV3 0.3%", + "poolFee": 0.003, + "tokenFrom": 1, + "tokenTo": 3, + "share": 0.42, + "assumedAmountIn": "41999949136593698816", + "assumedAmountOut": "17058670" + }, + { + "poolAddress": "0xf1A12338D39Fc085D8631E1A745B5116BC9b2A32", + "poolType": "Concentrated", + "poolName": "SushiSwapV3 0.05%", + "poolFee": 0.0005, + "tokenFrom": 1, + "tokenTo": 4, + "share": 0.07, + "assumedAmountIn": "6999991522765619200", + "assumedAmountOut": "1151083310209743" + }, + { + "poolAddress": "0x55FF76BFFC3Cdd9D5FdbBC2ece4528ECcE45047e", + "poolType": "Classic", + "poolName": "SushiSwapV2 0.3%", + "poolFee": 0.003, + "tokenFrom": 1, + "tokenTo": 5, + "share": 0.14, + "assumedAmountIn": "13999983045531238400", + "assumedAmountOut": "5688102" + }, + { + "poolAddress": "0x498d5cdcC5667b21210b49442Bf2D8792527194d", + "poolType": "Concentrated", + "poolName": "SushiSwapV3 0.01%", + "poolFee": 0.0001, + "tokenFrom": 5, + "tokenTo": 3, + "share": 1, + "assumedAmountIn": "5688102", + "assumedAmountOut": "5690476" + }, + { + "poolAddress": "0x34965ba0ac2451A34a0471F04CCa3F990b8dea27", + "poolType": "Classic", + "poolName": "SushiSwapV2 0.3%", + "poolFee": 0.003, + "tokenFrom": 4, + "tokenTo": 2, + "share": 0.7142811661133296, + "assumedAmountIn": "822189818431648", + "assumedAmountOut": "2032825" + }, + { + "poolAddress": "0x333923EC5bb34bf25468d77C641771e86Ee7bfCf", + "poolType": "Concentrated", + "poolName": "SushiSwapV3 0.01%", + "poolFee": 0.0001, + "tokenFrom": 4, + "tokenTo": 6, + "share": 0.2857188338866703, + "assumedAmountIn": "328893491778095", + "assumedAmountOut": "813735244605366656" + }, + { + "poolAddress": "0x4646E8A5e1d14E2DA01577822D6346c7883C6890", + "poolType": "Concentrated", + "poolName": "SushiSwapV3 0.01%", + "poolFee": 0.0001, + "tokenFrom": 6, + "tokenTo": 2, + "share": 1, + "assumedAmountIn": "813735244605366656", + "assumedAmountOut": "813679" + }, + { + "poolAddress": "0x00604DCc4463D6c39D957BC25C7b6683dDD2Ba90", + "poolType": "Concentrated", + "poolName": "SushiSwapV3 0.01%", + "poolFee": 0.0001, + "tokenFrom": 2, + "tokenTo": 3, "share": 1, - "assumedAmountIn": "100000000000000000000", - "assumedAmountOut": "89475609" + "assumedAmountIn": "17919775", + "assumedAmountOut": "17917411" } ], - "routeProcessorAddr": "0x46B3fDF7b5CDe91Ac049936bF0bDb12c5d22202e", - "routeProcessorArgs": { - "tokenIn": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", - "amountIn": "100000000000000000000", - "tokenOut": "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", - "amountOutMin": "89028230", - "to": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - "routeCode": "0x0301ffff020146B3fDF7b5CDe91Ac049936bF0bDb12c5d22202e0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270010d500B1d8E8eF31E21C99d1Db9A6444d3ADf127001ffff0121988C9CFD08db3b5793c2C6782271dC9474925101f39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - "value": "100000000000000000000", - "txdata": "0x2646478b000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000056bc75e2d631000000000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa8417400000000000000000000000000000000000000000000000000000000054e7686000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000700301ffff020146b3fdf7b5cde91ac049936bf0bdb12c5d22202e0d500b1d8e8ef31e21c99d1db9a6444d3adf1270010d500b1d8e8ef31e21c99d1db9a6444d3adf127001ffff0121988c9cfd08db3b5793c2c6782271dc9474925101f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000" + "routeProcessorAddr": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "tx": { + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "to": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "data": "0x2646478b000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000056bc75e2d631000000000000000000000000000003c499c542cef5e3811e1192ce70d8cc03d5c33590000000000000000000000000000000000000000000000000000000002696b78000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000022e0301ffff0201f2614A233c7C3e7f08b1F887Ba133a13f1eb2c550d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270010d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270045eb80121988C9CFD08db3b5793c2C6782271dC9474925101f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55aaaa01562A0460FE6cfc2E610AE5596c5b4ACe94d97C5601f39Fd6e51aad88F6F4ce6aB8827279cffFb92266555501f1A12338D39Fc085D8631E1A745B5116BC9b2A3201f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55ffff0055FF76BFFC3Cdd9D5FdbBC2ece4528ECcE45047e01f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55000bb801c2132D05D31c914a87C6611C10748AEb04B58e8F01ffff01498d5cdcC5667b21210b49442Bf2D8792527194d00f39Fd6e51aad88F6F4ce6aB8827279cffFb92266017ceB23fD6bC0adD59E62ac25578270cFf1b9f61902b6da0034965ba0ac2451A34a0471F04CCa3F990b8dea2700f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55000bb8ffff01333923EC5bb34bf25468d77C641771e86Ee7bfCf01f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55018f3Cf7ad23Cd3CaDbD9735AFf958023239c6A06301ffff014646E8A5e1d14E2DA01577822D6346c7883C689000f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55012791Bca1f2de4661ED88A30C99A7a9449Aa8417401ffff0100604DCc4463D6c39D957BC25C7b6683dDD2Ba9001f39Fd6e51aad88F6F4ce6aB8827279cffFb92266000000000000000000000000000000000000", + "value": "100000000000000000000" } -} +} \ No newline at end of file diff --git a/apps/web/test/swap/mock/137-native-to-usdt.json b/apps/web/test/swap/mock/137-native-to-usdt.json index cd79befd69..fd5b3a660f 100644 --- a/apps/web/test/swap/mock/137-native-to-usdt.json +++ b/apps/web/test/swap/mock/137-native-to-usdt.json @@ -19,6 +19,18 @@ "name": "USD Coin (PoS)", "decimals": 6 }, + { + "address": "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359", + "symbol": "USDC", + "name": "USD Coin", + "decimals": 6 + }, + { + "address": "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619", + "symbol": "WETH", + "name": "Wrapped Ether", + "decimals": 18 + }, { "address": "0xc2132D05D31c914a87C6611C10748AEb04B58e8F", "symbol": "USDT", @@ -27,13 +39,12 @@ } ], "tokenFrom": 0, - "tokenTo": 3, - "primaryPrice": 8.987142026149205e-13, - "swapPrice": 9.0201506e-13, - "priceImpact": -0.0036728666081777828, + "tokenTo": 5, + "swapPrice": 4.0649363999999977e-13, + "priceImpact": 0.004636128886240876, "amountIn": "100000000000000000000", - "assumedAmountOut": "90201506", - "gasSpent": 270000, + "assumedAmountOut": "40649364", + "gasSpent": 830000, "route": [ { "poolAddress": "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", @@ -43,8 +54,8 @@ "tokenFrom": 0, "tokenTo": 1, "share": 1, - "assumedAmountIn": "100000000000000000000", - "assumedAmountOut": "100000000000000000000" + "assumedAmountIn": "100000000000000065536", + "assumedAmountOut": "100000000000000065536" }, { "poolAddress": "0x21988C9CFD08db3b5793c2C6782271dC94749251", @@ -53,9 +64,64 @@ "poolFee": 0.0005, "tokenFrom": 1, "tokenTo": 2, + "share": 0.38, + "assumedAmountIn": "37999542229343125504", + "assumedAmountOut": "15479573" + }, + { + "poolAddress": "0x562A0460FE6cfc2E610AE5596c5b4ACe94d97C56", + "poolType": "Concentrated", + "poolName": "SushiSwapV3 0.3%", + "poolFee": 0.003, + "tokenFrom": 1, + "tokenTo": 3, + "share": 0.18, + "assumedAmountIn": "17999858236736385024", + "assumedAmountOut": "7316487" + }, + { + "poolAddress": "0xf1A12338D39Fc085D8631E1A745B5116BC9b2A32", + "poolType": "Concentrated", + "poolName": "SushiSwapV3 0.05%", + "poolFee": 0.0005, + "tokenFrom": 1, + "tokenTo": 4, + "share": 0.28, + "assumedAmountIn": "28000320484666552320", + "assumedAmountOut": "4604083697194467" + }, + { + "poolAddress": "0x55FF76BFFC3Cdd9D5FdbBC2ece4528ECcE45047e", + "poolType": "Classic", + "poolName": "SushiSwapV2 0.3%", + "poolFee": 0.003, + "tokenFrom": 1, + "tokenTo": 5, + "share": 0.16, + "assumedAmountIn": "16000279049253998592", + "assumedAmountOut": "6500259" + }, + { + "poolAddress": "0x498d5cdcC5667b21210b49442Bf2D8792527194d", + "poolType": "Concentrated", + "poolName": "SushiSwapV3 0.01%", + "poolFee": 0.0001, + "tokenFrom": 3, + "tokenTo": 5, "share": 1, - "assumedAmountIn": "100000000000000000000", - "assumedAmountOut": "90216219" + "assumedAmountIn": "7316487", + "assumedAmountOut": "7311963" + }, + { + "poolAddress": "0xEF69494EeA0ecBFbbFa1cfd5386268a562bc875F", + "poolType": "Concentrated", + "poolName": "SushiSwapV3 0.01%", + "poolFee": 0.0001, + "tokenFrom": 2, + "tokenTo": 4, + "share": 0.015195761677617376, + "assumedAmountIn": "235258", + "assumedAmountOut": "95384524746537" }, { "poolAddress": "0x8CFaab34f5159abf9C35587AC40d09a05dC94765", @@ -63,21 +129,28 @@ "poolName": "SushiSwapV3 0.01%", "poolFee": 0.0001, "tokenFrom": 2, - "tokenTo": 3, + "tokenTo": 5, + "share": 0.9848042383223826, + "assumedAmountIn": "15244315", + "assumedAmountOut": "15236047" + }, + { + "poolAddress": "0xc2755915a85C6f6c1C0F3a86ac8C058F11Caa9C9", + "poolType": "Classic", + "poolName": "SushiSwapV2 0.3%", + "poolFee": 0.003, + "tokenFrom": 4, + "tokenTo": 5, "share": 1, - "assumedAmountIn": "90216219", - "assumedAmountOut": "90201506" + "assumedAmountIn": "4699468221941004", + "assumedAmountOut": "11601095" } ], - "routeProcessorAddr": "0x46B3fDF7b5CDe91Ac049936bF0bDb12c5d22202e", - "routeProcessorArgs": { - "tokenIn": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", - "amountIn": "100000000000000000000", - "tokenOut": "0xc2132D05D31c914a87C6611C10748AEb04B58e8F", - "amountOutMin": "89750498", - "to": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - "routeCode": "0x0301ffff020146B3fDF7b5CDe91Ac049936bF0bDb12c5d22202e0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270010d500B1d8E8eF31E21C99d1Db9A6444d3ADf127001ffff0121988C9CFD08db3b5793c2C6782271dC947492510146B3fDF7b5CDe91Ac049936bF0bDb12c5d22202e012791Bca1f2de4661ED88A30C99A7a9449Aa8417401ffff018CFaab34f5159abf9C35587AC40d09a05dC9476501f39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - "value": "100000000000000000000", - "txdata": "0x2646478b000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000056bc75e2d63100000000000000000000000000000c2132d05d31c914a87c6611c10748aeb04b58e8f0000000000000000000000000000000000000000000000000000000005597be2000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000b20301ffff020146b3fdf7b5cde91ac049936bf0bdb12c5d22202e0d500b1d8e8ef31e21c99d1db9a6444d3adf1270010d500b1d8e8ef31e21c99d1db9a6444d3adf127001ffff0121988c9cfd08db3b5793c2c6782271dc947492510146b3fdf7b5cde91ac049936bf0bdb12c5d22202e012791bca1f2de4661ed88a30c99a7a9449aa8417401ffff018cfaab34f5159abf9c35587ac40d09a05dc9476501f39fd6e51aad88f6f4ce6ab8827279cfffb922660000000000000000000000000000" + "routeProcessorAddr": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "tx": { + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "to": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "data": "0x2646478b000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000056bc75e2d63100000000000000000000000000000c2132d05d31c914a87c6611c10748aeb04b58e8f00000000000000000000000000000000000000000000000000000000026928a5000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001e90301ffff0201f2614A233c7C3e7f08b1F887Ba133a13f1eb2c550d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270010d500B1d8E8eF31E21C99d1Db9A6444d3ADf12700461470121988C9CFD08db3b5793c2C6782271dC9474925101f2614A233c7C3e7f08b1F887Ba133a13f1eb2c554a5201562A0460FE6cfc2E610AE5596c5b4ACe94d97C5601f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55a2e801f1A12338D39Fc085D8631E1A745B5116BC9b2A3201c2755915a85C6f6c1C0F3a86ac8C058F11Caa9C9ffff0055FF76BFFC3Cdd9D5FdbBC2ece4528ECcE45047e01f39Fd6e51aad88F6F4ce6aB8827279cffFb92266000bb8013c499c542cEF5E3811e1192ce70d8cC03d5c335901ffff01498d5cdcC5667b21210b49442Bf2D8792527194d01f39Fd6e51aad88F6F4ce6aB8827279cffFb92266012791Bca1f2de4661ED88A30C99A7a9449Aa841740203e401EF69494EeA0ecBFbbFa1cfd5386268a562bc875F01c2755915a85C6f6c1C0F3a86ac8C058F11Caa9C9ffff018CFaab34f5159abf9C35587AC40d09a05dC9476501f39Fd6e51aad88F6F4ce6aB8827279cffFb92266047ceB23fD6bC0adD59E62ac25578270cFf1b9f61900c2755915a85C6f6c1C0F3a86ac8C058F11Caa9C901f39Fd6e51aad88F6F4ce6aB8827279cffFb92266000bb80000000000000000000000000000000000000000000000", + "value": "100000000000000000000" } -} +} \ No newline at end of file diff --git a/apps/web/test/swap/mock/137-native-to-wbtc.json b/apps/web/test/swap/mock/137-native-to-wbtc.json index 194c7f995a..28f3693a71 100644 --- a/apps/web/test/swap/mock/137-native-to-wbtc.json +++ b/apps/web/test/swap/mock/137-native-to-wbtc.json @@ -30,16 +30,21 @@ "symbol": "WETH", "name": "Wrapped Ether", "decimals": 18 + }, + { + "address": "0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063", + "symbol": "DAI", + "name": "(PoS) Dai Stablecoin", + "decimals": 18 } ], "tokenFrom": 0, "tokenTo": 2, - "primaryPrice": 1.37006827218446e-15, - "swapPrice": 1.3674571428571432e-15, - "priceImpact": 0.0019058388405371884, - "amountIn": "7000000000000000000000", - "assumedAmountOut": "9572200", - "gasSpent": 640000, + "swapPrice": 7.0738999999999955e-16, + "priceImpact": 0.005572786531761298, + "amountIn": "100000000000000000000", + "assumedAmountOut": "70739", + "gasSpent": 950000, "route": [ { "poolAddress": "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", @@ -49,74 +54,125 @@ "tokenFrom": 0, "tokenTo": 1, "share": 1, - "assumedAmountIn": "6999999999999997902848", - "assumedAmountOut": "6999999999999997902848" + "assumedAmountIn": "100000000000000065536", + "assumedAmountOut": "100000000000000065536" }, { - "poolAddress": "0x6b75F2189F0E11C52e814E09e280eb1a9A8A094a", - "poolType": "Concentrated", - "poolName": "UniswapV3 0.05%", - "poolFee": 0.0005, + "poolAddress": "0x8531c4e29491fE6e5e87AF6054FC20FcCf0b4290", + "poolType": "Classic", + "poolName": "SushiSwapV2 0.3%", + "poolFee": 0.003, "tokenFrom": 1, "tokenTo": 2, - "share": 0.07142857142857142, - "assumedAmountIn": "499992370489051447296", - "assumedAmountOut": "683935" + "share": 0.02, + "assumedAmountIn": "2000457770656902144", + "assumedAmountOut": "1416" }, { - "poolAddress": "0xA374094527e1673A86dE625aa59517c5dE346d32", + "poolAddress": "0x21988C9CFD08db3b5793c2C6782271dC94749251", "poolType": "Concentrated", - "poolName": "UniswapV3 0.05%", + "poolName": "SushiSwapV3 0.05%", "poolFee": 0.0005, "tokenFrom": 1, "tokenTo": 3, - "share": 0.07142857142857142, - "assumedAmountIn": "499985327845650137088", - "assumedAmountOut": "447380321" + "share": 0.12, + "assumedAmountIn": "12000401714968776704", + "assumedAmountOut": "4895627" + }, + { + "poolAddress": "0xc4e595acDD7d12feC385E5dA5D43160e8A0bAC0E", + "poolType": "Classic", + "poolName": "SushiSwapV2 0.3%", + "poolFee": 0.003, + "tokenFrom": 1, + "tokenTo": 4, + "share": 0.25, + "assumedAmountIn": "24999917997090816000", + "assumedAmountOut": "4109533463103143" }, { - "poolAddress": "0x86f1d8390222A3691C28938eC7404A1661E618e0", + "poolAddress": "0xf1A12338D39Fc085D8631E1A745B5116BC9b2A32", "poolType": "Concentrated", - "poolName": "UniswapV3 0.05%", + "poolName": "SushiSwapV3 0.05%", "poolFee": 0.0005, "tokenFrom": 1, "tokenTo": 4, - "share": 0.8571428571428571, - "assumedAmountIn": "6000022301665296121856", - "assumedAmountOut": "1624168160711454976" + "share": 0.61, + "assumedAmountIn": "60999222517283569664", + "assumedAmountOut": "10029028996212864" + }, + { + "poolAddress": "0xD02b870c556480491c70AaF98C297fddd93F6f5C", + "poolType": "Classic", + "poolName": "SushiSwapV2 0.3%", + "poolFee": 0.003, + "tokenFrom": 3, + "tokenTo": 2, + "share": 0.1667040252283369, + "assumedAmountIn": "816124", + "assumedAmountOut": "1421" }, { - "poolAddress": "0x50eaEDB835021E4A108B7290636d62E9765cc6d7", + "poolAddress": "0xF88dE8Aaa065EcBF9a3C67f7A93b4c82595f6D6F", "poolType": "Concentrated", - "poolName": "UniswapV3 0.05%", - "poolFee": 0.0005, - "tokenFrom": 4, + "poolName": "SushiSwapV3 0.3%", + "poolFee": 0.003, + "tokenFrom": 3, "tokenTo": 2, - "share": 1, - "assumedAmountIn": "1624168160711454976", - "assumedAmountOut": "8204604" + "share": 0.6666479818920626, + "assumedAmountIn": "3263664", + "assumedAmountOut": "5676" }, { - "poolAddress": "0xeEF1A9507B3D505f0062f2be9453981255b503c8", + "poolAddress": "0xEF69494EeA0ecBFbbFa1cfd5386268a562bc875F", "poolType": "Concentrated", - "poolName": "UniswapV3 0.05%", - "poolFee": 0.0005, + "poolName": "SushiSwapV3 0.01%", + "poolFee": 0.0001, + "tokenFrom": 3, + "tokenTo": 4, + "share": 0.08335667373140918, + "assumedAmountIn": "408075", + "assumedAmountOut": "165260487355010" + }, + { + "poolAddress": "0x4646E8A5e1d14E2DA01577822D6346c7883C6890", + "poolType": "Concentrated", + "poolName": "SushiSwapV3 0.01%", + "poolFee": 0.0001, "tokenFrom": 3, + "tokenTo": 5, + "share": 0.08329131914819138, + "assumedAmountIn": "407764", + "assumedAmountOut": "407710272319493824" + }, + { + "poolAddress": "0x333923EC5bb34bf25468d77C641771e86Ee7bfCf", + "poolType": "Concentrated", + "poolName": "SushiSwapV3 0.01%", + "poolFee": 0.0001, + "tokenFrom": 5, + "tokenTo": 4, + "share": 1, + "assumedAmountIn": "407710272319493824", + "assumedAmountOut": "164483051446041" + }, + { + "poolAddress": "0xE62Ec2e799305E0D367b0Cc3ee2CdA135bF89816", + "poolType": "Classic", + "poolName": "SushiSwapV2 0.3%", + "poolFee": 0.003, + "tokenFrom": 4, "tokenTo": 2, "share": 1, - "assumedAmountIn": "447380321", - "assumedAmountOut": "683661" + "assumedAmountIn": "14468305998117060", + "assumedAmountOut": "62226" } ], - "routeProcessorAddr": "0x46B3fDF7b5CDe91Ac049936bF0bDb12c5d22202e", - "routeProcessorArgs": { - "tokenIn": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", - "amountIn": "7000000000000000000000", - "tokenOut": "0x1BFD67037B42Cf73acF2047067bd4F2C47D9BfD6", - "amountOutMin": "9524339", - "to": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - "routeCode": "0x0301ffff020146B3fDF7b5CDe91Ac049936bF0bDb12c5d22202e0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270010d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270031249016b75F2189F0E11C52e814E09e280eb1a9A8A094a01f39Fd6e51aad88F6F4ce6aB8827279cffFb9226613b101A374094527e1673A86dE625aa59517c5dE346d320146B3fDF7b5CDe91Ac049936bF0bDb12c5d22202effff0186f1d8390222A3691C28938eC7404A1661E618e00146B3fDF7b5CDe91Ac049936bF0bDb12c5d22202e017ceB23fD6bC0adD59E62ac25578270cFf1b9f61901ffff0150eaEDB835021E4A108B7290636d62E9765cc6d700f39Fd6e51aad88F6F4ce6aB8827279cffFb92266012791Bca1f2de4661ED88A30C99A7a9449Aa8417401ffff01eEF1A9507B3D505f0062f2be9453981255b503c800f39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - "value": "7000000000000000000000", - "txdata": "0x2646478b000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee00000000000000000000000000000000000000000000017b7883c069166000000000000000000000000000001bfd67037b42cf73acf2047067bd4f2c47d9bfd60000000000000000000000000000000000000000000000000000000000915473000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000014c0301ffff020146b3fdf7b5cde91ac049936bf0bdb12c5d22202e0d500b1d8e8ef31e21c99d1db9a6444d3adf1270010d500b1d8e8ef31e21c99d1db9a6444d3adf1270031249016b75f2189f0e11c52e814e09e280eb1a9a8a094a01f39fd6e51aad88f6f4ce6ab8827279cfffb9226613b101a374094527e1673a86de625aa59517c5de346d320146b3fdf7b5cde91ac049936bf0bdb12c5d22202effff0186f1d8390222a3691c28938ec7404a1661e618e00146b3fdf7b5cde91ac049936bf0bdb12c5d22202e017ceb23fd6bc0add59e62ac25578270cff1b9f61901ffff0150eaedb835021e4a108b7290636d62e9765cc6d700f39fd6e51aad88f6f4ce6ab8827279cfffb92266012791bca1f2de4661ed88a30c99a7a9449aa8417401ffff01eef1a9507b3d505f0062f2be9453981255b503c800f39fd6e51aad88f6f4ce6ab8827279cfffb922660000000000000000000000000000000000000000" + "routeProcessorAddr": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "tx": { + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "to": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "data": "0x6678ec1f000000000000000000000000850a57630a2012b2494779fbc86bbc24f2a7baef00000000000000000000000000000000000000000000000000000000000000af000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000056bc75e2d631000000000000000000000000000001bfd67037b42cf73acf2047067bd4f2c47d9bfd600000000000000000000000000000000000000000000000000000000000112f1000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002470301ffff0201f2614A233c7C3e7f08b1F887Ba133a13f1eb2c550d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270010d500B1d8E8eF31E21C99d1Db9A6444d3ADf127004051f008531c4e29491fE6e5e87AF6054FC20FcCf0b429001f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55000bb81f590121988C9CFD08db3b5793c2C6782271dC9474925101f2614A233c7C3e7f08b1F887Ba133a13f1eb2c554a6b00c4e595acDD7d12feC385E5dA5D43160e8A0bAC0E01E62Ec2e799305E0D367b0Cc3ee2CdA135bF89816000bb8ffff01f1A12338D39Fc085D8631E1A745B5116BC9b2A3201E62Ec2e799305E0D367b0Cc3ee2CdA135bF89816012791Bca1f2de4661ED88A30C99A7a9449Aa84174042aad00D02b870c556480491c70AaF98C297fddd93F6f5C00f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55000bb8cccd01F88dE8Aaa065EcBF9a3C67f7A93b4c82595f6D6F00f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55800c01EF69494EeA0ecBFbbFa1cfd5386268a562bc875F01E62Ec2e799305E0D367b0Cc3ee2CdA135bF89816ffff014646E8A5e1d14E2DA01577822D6346c7883C689001f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55018f3Cf7ad23Cd3CaDbD9735AFf958023239c6A06301ffff01333923EC5bb34bf25468d77C641771e86Ee7bfCf00E62Ec2e799305E0D367b0Cc3ee2CdA135bF89816047ceB23fD6bC0adD59E62ac25578270cFf1b9f61900E62Ec2e799305E0D367b0Cc3ee2CdA135bF8981600f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55000bb800000000000000000000000000000000000000000000000000", + "value": "100000000000000000000" } -} +} \ No newline at end of file diff --git a/apps/web/test/swap/mock/137-unwrap.json b/apps/web/test/swap/mock/137-unwrap.json index 7836b76b09..8cc6f508a0 100644 --- a/apps/web/test/swap/mock/137-unwrap.json +++ b/apps/web/test/swap/mock/137-unwrap.json @@ -16,11 +16,10 @@ ], "tokenFrom": 0, "tokenTo": 1, - "primaryPrice": 1, "swapPrice": 1, "priceImpact": 0, - "amountIn": "10000000000000000000", - "assumedAmountOut": "10000000000000000000", + "amountIn": "100000000000000000000", + "assumedAmountOut": "100000000000000000000", "gasSpent": 50000, "route": [ { @@ -31,18 +30,14 @@ "tokenFrom": 0, "tokenTo": 1, "share": 1, - "assumedAmountIn": "10000000000000000000", - "assumedAmountOut": "10000000000000000000" + "assumedAmountIn": "100000000000000000000", + "assumedAmountOut": "100000000000000000000" } ], - "routeProcessorAddr": "0x46B3fDF7b5CDe91Ac049936bF0bDb12c5d22202e", - "routeProcessorArgs": { - "tokenIn": "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", - "amountIn": "10000000000000000000", - "tokenOut": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", - "amountOutMin": "10000000000000000000", - "to": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - "routeCode": "0x020d500B1d8E8eF31E21C99d1Db9A6444d3ADf127001ffff0200f39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - "txdata": "0x2646478b0000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf12700000000000000000000000000000000000000000000000008ac7230489e80000000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000008ac7230489e80000000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000002e020d500b1d8e8ef31e21c99d1db9a6444d3adf127001ffff0200f39fd6e51aad88f6f4ce6ab8827279cfffb92266000000000000000000000000000000000000" + "routeProcessorAddr": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "tx": { + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "to": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "data": "0x2646478b0000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf12700000000000000000000000000000000000000000000000056bc75e2d63100000000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000056bc75e2d63100000000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000002e020d500B1d8E8eF31E21C99d1Db9A6444d3ADf127001ffff0200f39Fd6e51aad88F6F4ce6aB8827279cffFb92266000000000000000000000000000000000000" } -} +} \ No newline at end of file diff --git a/apps/web/test/swap/mock/137-usdc-to-native.json b/apps/web/test/swap/mock/137-usdc-to-native.json index b611412977..b289a3a97e 100644 --- a/apps/web/test/swap/mock/137-usdc-to-native.json +++ b/apps/web/test/swap/mock/137-usdc-to-native.json @@ -1,18 +1,48 @@ { "status": "Success", "tokens": [ + { + "address": "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359", + "symbol": "USDC", + "name": "USD Coin", + "decimals": 6 + }, { "address": "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", "symbol": "USDC", "name": "USD Coin (PoS)", "decimals": 6 }, + { + "address": "0xc2132D05D31c914a87C6611C10748AEb04B58e8F", + "symbol": "USDT", + "name": "(PoS) Tether USD", + "decimals": 6 + }, { "address": "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", "symbol": "WMATIC", "name": "Wrapped Matic", "decimals": 18 }, + { + "address": "0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063", + "symbol": "DAI", + "name": "(PoS) Dai Stablecoin", + "decimals": 18 + }, + { + "address": "0xD6DF932A45C0f255f85145f286eA0b292B21C90B", + "symbol": "AAVE", + "name": "Aave (PoS)", + "decimals": 18 + }, + { + "address": "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619", + "symbol": "WETH", + "name": "Wrapped Ether", + "decimals": 18 + }, { "address": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", "symbol": "MATIC", @@ -21,45 +51,139 @@ } ], "tokenFrom": 0, - "tokenTo": 2, - "primaryPrice": 1117186443275.135, - "swapPrice": 1112058845263.2546, - "priceImpact": 0.004589742421908016, - "amountIn": "89475609", - "assumedAmountOut": "99502142423766499328", - "gasSpent": 160000, + "tokenTo": 7, + "swapPrice": 2454483305408.1904, + "priceImpact": -0.0012706043226990982, + "amountIn": "1000000", + "assumedAmountOut": "2454483305408190464", + "gasSpent": 1090000, "route": [ { - "poolAddress": "0x21988C9CFD08db3b5793c2C6782271dC94749251", + "poolAddress": "0x00604DCc4463D6c39D957BC25C7b6683dDD2Ba90", "poolType": "Concentrated", - "poolName": "SushiSwapV3 0.05%", - "poolFee": 0.0005, + "poolName": "SushiSwapV3 0.01%", + "poolFee": 0.0001, "tokenFrom": 0, "tokenTo": 1, + "share": 0.3333333333333333, + "assumedAmountIn": "333333", + "assumedAmountOut": "333309" + }, + { + "poolAddress": "0x498d5cdcC5667b21210b49442Bf2D8792527194d", + "poolType": "Concentrated", + "poolName": "SushiSwapV3 0.01%", + "poolFee": 0.0001, + "tokenFrom": 0, + "tokenTo": 2, + "share": 0.6666666666666666, + "assumedAmountIn": "666667", + "assumedAmountOut": "666254" + }, + { + "poolAddress": "0xdB0101bE2132408e65B30246aa662e4D6f49599c", + "poolType": "Concentrated", + "poolName": "SushiSwapV3 0.3%", + "poolFee": 0.003, + "tokenFrom": 2, + "tokenTo": 3, + "share": 0.7499999999999997, + "assumedAmountIn": "499687", + "assumedAmountOut": "1224956348951011840" + }, + { + "poolAddress": "0x7e5Fc5677Dfb16dFBC250AFf8F90E6ceF743Ca01", + "poolType": "Concentrated", + "poolName": "SushiSwapV3 0.01%", + "poolFee": 0.0001, + "tokenFrom": 2, + "tokenTo": 4, + "share": 0.12499999466481652, + "assumedAmountIn": "83282", + "assumedAmountOut": "83240476591060048" + }, + { + "poolAddress": "0xa543Ba3fd79a03788e5521a0Ce48B3F2Bf93b2c1", + "poolType": "Classic", + "poolName": "SushiSwapV2 0.3%", + "poolFee": 0.003, + "tokenFrom": 2, + "tokenTo": 5, + "share": 0.12500000533518382, + "assumedAmountIn": "83285", + "assumedAmountOut": "822829204479297" + }, + { + "poolAddress": "0x7d88D931504D04BFBEE6F9745297A93063CAb24c", + "poolType": "Classic", + "poolName": "SushiSwapV2 0.3%", + "poolFee": 0.003, + "tokenFrom": 5, + "tokenTo": 3, + "share": 1, + "assumedAmountIn": "822829204479297", + "assumedAmountOut": "204645614090705952" + }, + { + "poolAddress": "0xe58517662569c742388b90dC5461F7DBBBD8aE58", + "poolType": "Concentrated", + "poolName": "SushiSwapV3 0.3%", + "poolFee": 0.003, + "tokenFrom": 4, + "tokenTo": 3, + "share": 1, + "assumedAmountIn": "83240476591060048", + "assumedAmountOut": "204624511482240192" + }, + { + "poolAddress": "0x934F3F8749164111f0386eCE4f4965a687E576d5", + "poolType": "Concentrated", + "poolName": "SushiSwapV3 0.01%", + "poolFee": 0.0001, + "tokenFrom": 1, + "tokenTo": 3, + "share": 0.24999999895779174, + "assumedAmountIn": "83328", + "assumedAmountOut": "204592268592704096" + }, + { + "poolAddress": "0xEF69494EeA0ecBFbbFa1cfd5386268a562bc875F", + "poolType": "Concentrated", + "poolName": "SushiSwapV3 0.01%", + "poolFee": 0.0001, + "tokenFrom": 1, + "tokenTo": 6, + "share": 0.7500000010422082, + "assumedAmountIn": "249981", + "assumedAmountOut": "101344067904539" + }, + { + "poolAddress": "0xf1A12338D39Fc085D8631E1A745B5116BC9b2A32", + "poolType": "Concentrated", + "poolName": "SushiSwapV3 0.05%", + "poolFee": 0.0005, + "tokenFrom": 6, + "tokenTo": 3, "share": 1, - "assumedAmountIn": "89475609", - "assumedAmountOut": "99502142423766482944" + "assumedAmountIn": "101344067904539", + "assumedAmountOut": "615664562291528320" }, { "poolAddress": "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", "poolType": "Bridge", "poolName": "Wrap", "poolFee": 0, - "tokenFrom": 1, - "tokenTo": 2, + "tokenFrom": 3, + "tokenTo": 7, "share": 1, - "assumedAmountIn": "99502142423766482944", - "assumedAmountOut": "99502142423766482944" + "assumedAmountIn": "2454483305408190464", + "assumedAmountOut": "2454483305408190464" } ], - "routeProcessorAddr": "0x46B3fDF7b5CDe91Ac049936bF0bDb12c5d22202e", - "routeProcessorArgs": { - "tokenIn": "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", - "amountIn": "89475609", - "tokenOut": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", - "amountOutMin": "99004631711647666831", - "to": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - "routeCode": "0x022791Bca1f2de4661ED88A30C99A7a9449Aa8417401ffff0121988C9CFD08db3b5793c2C6782271dC947492510046B3fDF7b5CDe91Ac049936bF0bDb12c5d22202e010d500B1d8E8eF31E21C99d1Db9A6444d3ADf127001ffff0200f39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - "txdata": "0x2646478b0000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa841740000000000000000000000000000000000000000000000000000000005554a19000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000055df71bfe2322128f000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000070022791bca1f2de4661ed88a30c99a7a9449aa8417401ffff0121988c9cfd08db3b5793c2c6782271dc947492510046b3fdf7b5cde91ac049936bf0bdb12c5d22202e010d500b1d8e8ef31e21c99d1db9a6444d3adf127001ffff0200f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000" + "routeProcessorAddr": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "tx": { + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "to": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "data": "0x2646478b0000000000000000000000003c499c542cef5e3811e1192ce70d8cc03d5c335900000000000000000000000000000000000000000000000000000000000f4240000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee00000000000000000000000000000000000000000000000021e479dd325a1647000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000026d023c499c542cEF5E3811e1192ce70d8cC03d5c33590255550100604DCc4463D6c39D957BC25C7b6683dDD2Ba9000f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55ffff01498d5cdcC5667b21210b49442Bf2D8792527194d01f2614A233c7C3e7f08b1F887Ba133a13f1eb2c5501c2132D05D31c914a87C6611C10748AEb04B58e8F03bfff01dB0101bE2132408e65B30246aa662e4D6f49599c00f2614A233c7C3e7f08b1F887Ba133a13f1eb2c557fff017e5Fc5677Dfb16dFBC250AFf8F90E6ceF743Ca0100f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55ffff00a543Ba3fd79a03788e5521a0Ce48B3F2Bf93b2c1017d88D931504D04BFBEE6F9745297A93063CAb24c000bb804D6DF932A45C0f255f85145f286eA0b292B21C90B007d88D931504D04BFBEE6F9745297A93063CAb24c00f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55000bb8018f3Cf7ad23Cd3CaDbD9735AFf958023239c6A06301ffff01e58517662569c742388b90dC5461F7DBBBD8aE5800f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55012791Bca1f2de4661ED88A30C99A7a9449Aa8417402400001934F3F8749164111f0386eCE4f4965a687E576d500f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55ffff01EF69494EeA0ecBFbbFa1cfd5386268a562bc875F01f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55017ceB23fD6bC0adD59E62ac25578270cFf1b9f61901ffff01f1A12338D39Fc085D8631E1A745B5116BC9b2A3200f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55010d500B1d8E8eF31E21C99d1Db9A6444d3ADf127001ffff0200f39Fd6e51aad88F6F4ce6aB8827279cffFb9226600000000000000000000000000000000000000" } -} +} \ No newline at end of file diff --git a/apps/web/test/swap/mock/137-usdc-to-usdt.json b/apps/web/test/swap/mock/137-usdc-to-usdt.json index 28484fec06..d167803b68 100644 --- a/apps/web/test/swap/mock/137-usdc-to-usdt.json +++ b/apps/web/test/swap/mock/137-usdc-to-usdt.json @@ -2,9 +2,9 @@ "status": "Success", "tokens": [ { - "address": "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", + "address": "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359", "symbol": "USDC", - "name": "USD Coin (PoS)", + "name": "USD Coin", "decimals": 6 }, { @@ -16,33 +16,28 @@ ], "tokenFrom": 0, "tokenTo": 1, - "primaryPrice": 0.9996994705657433, - "swapPrice": 0.9996473370786517, - "priceImpact": 0.00005214915944895537, - "amountIn": "89000000", - "assumedAmountOut": "88968613", + "swapPrice": 0.9993819999999993, + "priceImpact": 0.0017230930770902875, + "amountIn": "1000000", + "assumedAmountOut": "999382", "gasSpent": 110000, "route": [ { - "poolAddress": "0x8CFaab34f5159abf9C35587AC40d09a05dC94765", + "poolAddress": "0x498d5cdcC5667b21210b49442Bf2D8792527194d", "poolType": "Concentrated", "poolName": "SushiSwapV3 0.01%", "poolFee": 0.0001, "tokenFrom": 0, "tokenTo": 1, "share": 1, - "assumedAmountIn": "89000000", - "assumedAmountOut": "88968613" + "assumedAmountIn": "1000000", + "assumedAmountOut": "999382" } ], - "routeProcessorAddr": "0x46B3fDF7b5CDe91Ac049936bF0bDb12c5d22202e", - "routeProcessorArgs": { - "tokenIn": "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", - "amountIn": "89000000", - "tokenOut": "0xc2132D05D31c914a87C6611C10748AEb04B58e8F", - "amountOutMin": "88523769", - "to": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - "routeCode": "0x022791Bca1f2de4661ED88A30C99A7a9449Aa8417401ffff018CFaab34f5159abf9C35587AC40d09a05dC9476501f39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - "txdata": "0x2646478b0000000000000000000000002791bca1f2de4661ed88a30c99a7a9449aa8417400000000000000000000000000000000000000000000000000000000054e0840000000000000000000000000c2132d05d31c914a87c6611c10748aeb04b58e8f000000000000000000000000000000000000000000000000000000000546c3f9000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000042022791bca1f2de4661ed88a30c99a7a9449aa8417401ffff018cfaab34f5159abf9c35587ac40d09a05dc9476501f39fd6e51aad88f6f4ce6ab8827279cfffb92266000000000000000000000000000000000000000000000000000000000000" + "routeProcessorAddr": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "tx": { + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "to": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "data": "0x2646478b0000000000000000000000003c499c542cef5e3811e1192ce70d8cc03d5c335900000000000000000000000000000000000000000000000000000000000f4240000000000000000000000000c2132d05d31c914a87c6611c10748aeb04b58e8f00000000000000000000000000000000000000000000000000000000000f2c51000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000042023c499c542cEF5E3811e1192ce70d8cC03d5c335901ffff01498d5cdcC5667b21210b49442Bf2D8792527194d01f39Fd6e51aad88F6F4ce6aB8827279cffFb92266000000000000000000000000000000000000000000000000000000000000" } -} +} \ No newline at end of file diff --git a/apps/web/test/swap/mock/137-usdt-to-native.json b/apps/web/test/swap/mock/137-usdt-to-native.json index 3d27d7fe50..e67945443d 100644 --- a/apps/web/test/swap/mock/137-usdt-to-native.json +++ b/apps/web/test/swap/mock/137-usdt-to-native.json @@ -7,6 +7,30 @@ "name": "(PoS) Tether USD", "decimals": 6 }, + { + "address": "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", + "symbol": "WMATIC", + "name": "Wrapped Matic", + "decimals": 18 + }, + { + "address": "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359", + "symbol": "USDC", + "name": "USD Coin", + "decimals": 6 + }, + { + "address": "0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063", + "symbol": "DAI", + "name": "(PoS) Dai Stablecoin", + "decimals": 18 + }, + { + "address": "0xD6DF932A45C0f255f85145f286eA0b292B21C90B", + "symbol": "AAVE", + "name": "Aave (PoS)", + "decimals": 18 + }, { "address": "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", "symbol": "USDC", @@ -14,52 +38,141 @@ "decimals": 6 }, { - "address": "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", - "symbol": "WMATIC", - "name": "Wrapped Matic", + "address": "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619", + "symbol": "WETH", + "name": "Wrapped Ether", + "decimals": 18 + }, + { + "address": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", + "symbol": "MATIC", + "name": "MATIC", "decimals": 18 } ], "tokenFrom": 0, - "tokenTo": 2, - "primaryPrice": 1120537665908.718, - "swapPrice": 1116440723126.4507, - "priceImpact": 0.0036562294217435953, - "amountIn": "89000000", - "assumedAmountOut": "99363224358254116864", - "gasSpent": 220000, + "tokenTo": 7, + "swapPrice": 2455069920207.021, + "priceImpact": -0.0026185772674121033, + "amountIn": "1000000", + "assumedAmountOut": "2455069920207021056", + "gasSpent": 980000, "route": [ { - "poolAddress": "0x8CFaab34f5159abf9C35587AC40d09a05dC94765", + "poolAddress": "0xdB0101bE2132408e65B30246aa662e4D6f49599c", + "poolType": "Concentrated", + "poolName": "SushiSwapV3 0.3%", + "poolFee": 0.003, + "tokenFrom": 0, + "tokenTo": 1, + "share": 0.5833333333333333, + "assumedAmountIn": "583337", + "assumedAmountOut": "1429646812130815488" + }, + { + "poolAddress": "0x498d5cdcC5667b21210b49442Bf2D8792527194d", "poolType": "Concentrated", "poolName": "SushiSwapV3 0.01%", "poolFee": 0.0001, "tokenFrom": 0, + "tokenTo": 2, + "share": 0.25, + "assumedAmountIn": "249997", + "assumedAmountOut": "250101" + }, + { + "poolAddress": "0x7e5Fc5677Dfb16dFBC250AFf8F90E6ceF743Ca01", + "poolType": "Concentrated", + "poolName": "SushiSwapV3 0.01%", + "poolFee": 0.0001, + "tokenFrom": 0, + "tokenTo": 3, + "share": 0.08333333333333333, + "assumedAmountIn": "83331", + "assumedAmountOut": "83289426837355936" + }, + { + "poolAddress": "0xa543Ba3fd79a03788e5521a0Ce48B3F2Bf93b2c1", + "poolType": "Classic", + "poolName": "SushiSwapV2 0.3%", + "poolFee": 0.003, + "tokenFrom": 0, + "tokenTo": 4, + "share": 0.08333333333333333, + "assumedAmountIn": "83335", + "assumedAmountOut": "823321492277830" + }, + { + "poolAddress": "0x7d88D931504D04BFBEE6F9745297A93063CAb24c", + "poolType": "Classic", + "poolName": "SushiSwapV2 0.3%", + "poolFee": 0.003, + "tokenFrom": 4, "tokenTo": 1, "share": 1, - "assumedAmountIn": "89000000", - "assumedAmountOut": "89011500" + "assumedAmountIn": "823321492277830", + "assumedAmountOut": "204768029241574560" + }, + { + "poolAddress": "0xe58517662569c742388b90dC5461F7DBBBD8aE58", + "poolType": "Concentrated", + "poolName": "SushiSwapV3 0.3%", + "poolFee": 0.003, + "tokenFrom": 3, + "tokenTo": 1, + "share": 1, + "assumedAmountIn": "83289426837355936", + "assumedAmountOut": "204744622631952640" + }, + { + "poolAddress": "0x00604DCc4463D6c39D957BC25C7b6683dDD2Ba90", + "poolType": "Concentrated", + "poolName": "SushiSwapV3 0.01%", + "poolFee": 0.0001, + "tokenFrom": 2, + "tokenTo": 5, + "share": 1, + "assumedAmountIn": "250101", + "assumedAmountOut": "250082" }, { - "poolAddress": "0x21988C9CFD08db3b5793c2C6782271dC94749251", + "poolAddress": "0xEF69494EeA0ecBFbbFa1cfd5386268a562bc875F", + "poolType": "Concentrated", + "poolName": "SushiSwapV3 0.01%", + "poolFee": 0.0001, + "tokenFrom": 5, + "tokenTo": 6, + "share": 1, + "assumedAmountIn": "250082", + "assumedAmountOut": "101384544390673" + }, + { + "poolAddress": "0xf1A12338D39Fc085D8631E1A745B5116BC9b2A32", "poolType": "Concentrated", "poolName": "SushiSwapV3 0.05%", "poolFee": 0.0005, + "tokenFrom": 6, + "tokenTo": 1, + "share": 1, + "assumedAmountIn": "101384544390673", + "assumedAmountOut": "615910456202678272" + }, + { + "poolAddress": "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", + "poolType": "Bridge", + "poolName": "Wrap", + "poolFee": 0, "tokenFrom": 1, - "tokenTo": 2, + "tokenTo": 7, "share": 1, - "assumedAmountIn": "89011500", - "assumedAmountOut": "99363224358254100480" + "assumedAmountIn": "2455069920207021056", + "assumedAmountOut": "2455069920207021056" } ], - "routeProcessorAddr": "0x46B3fDF7b5CDe91Ac049936bF0bDb12c5d22202e", - "routeProcessorArgs": { - "tokenIn": "0xc2132D05D31c914a87C6611C10748AEb04B58e8F", - "amountIn": "89000000", - "tokenOut": "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", - "amountOutMin": "98866408236462846279", - "to": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - "routeCode": "0x02c2132D05D31c914a87C6611C10748AEb04B58e8F01ffff018CFaab34f5159abf9C35587AC40d09a05dC947650046B3fDF7b5CDe91Ac049936bF0bDb12c5d22202e012791Bca1f2de4661ED88A30C99A7a9449Aa8417401ffff0121988C9CFD08db3b5793c2C6782271dC9474925100f39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - "txdata": "0x2646478b000000000000000000000000c2132d05d31c914a87c6611c10748aeb04b58e8f00000000000000000000000000000000000000000000000000000000054e08400000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf12700000000000000000000000000000000000000000000000055c0c0a79711f3147000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000008402c2132d05d31c914a87c6611c10748aeb04b58e8f01ffff018cfaab34f5159abf9c35587ac40d09a05dc947650046b3fdf7b5cde91ac049936bf0bdb12c5d22202e012791bca1f2de4661ed88a30c99a7a9449aa8417401ffff0121988c9cfd08db3b5793c2c6782271dc9474925100f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000" + "routeProcessorAddr": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "tx": { + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "to": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "data": "0x2646478b000000000000000000000000c2132d05d31c914a87c6611c10748aeb04b58e8f00000000000000000000000000000000000000000000000000000000000f4240000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee00000000000000000000000000000000000000000000000021e68cb83039009e000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000024102c2132D05D31c914a87C6611C10748AEb04B58e8F04955501dB0101bE2132408e65B30246aa662e4D6f49599c00f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55999901498d5cdcC5667b21210b49442Bf2D8792527194d00f2614A233c7C3e7f08b1F887Ba133a13f1eb2c557fff017e5Fc5677Dfb16dFBC250AFf8F90E6ceF743Ca0100f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55ffff00a543Ba3fd79a03788e5521a0Ce48B3F2Bf93b2c1017d88D931504D04BFBEE6F9745297A93063CAb24c000bb804D6DF932A45C0f255f85145f286eA0b292B21C90B007d88D931504D04BFBEE6F9745297A93063CAb24c00f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55000bb8018f3Cf7ad23Cd3CaDbD9735AFf958023239c6A06301ffff01e58517662569c742388b90dC5461F7DBBBD8aE5800f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55013c499c542cEF5E3811e1192ce70d8cC03d5c335901ffff0100604DCc4463D6c39D957BC25C7b6683dDD2Ba9000f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55012791Bca1f2de4661ED88A30C99A7a9449Aa8417401ffff01EF69494EeA0ecBFbbFa1cfd5386268a562bc875F01f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55017ceB23fD6bC0adD59E62ac25578270cFf1b9f61901ffff01f1A12338D39Fc085D8631E1A745B5116BC9b2A3200f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55010d500B1d8E8eF31E21C99d1Db9A6444d3ADf127001ffff0200f39Fd6e51aad88F6F4ce6aB8827279cffFb9226600000000000000000000000000000000000000000000000000000000000000" } -} +} \ No newline at end of file diff --git a/apps/web/test/swap/mock/137-wrap.json b/apps/web/test/swap/mock/137-wrap.json index f46a478672..19f946d646 100644 --- a/apps/web/test/swap/mock/137-wrap.json +++ b/apps/web/test/swap/mock/137-wrap.json @@ -16,11 +16,10 @@ ], "tokenFrom": 0, "tokenTo": 1, - "primaryPrice": 1, "swapPrice": 1, "priceImpact": 0, - "amountIn": "10000000000000000000", - "assumedAmountOut": "10000000000000000000", + "amountIn": "100000000000000000000", + "assumedAmountOut": "100000000000000000000", "gasSpent": 50000, "route": [ { @@ -31,19 +30,15 @@ "tokenFrom": 0, "tokenTo": 1, "share": 1, - "assumedAmountIn": "10000000000000000000", - "assumedAmountOut": "10000000000000000000" + "assumedAmountIn": "100000000000000000000", + "assumedAmountOut": "100000000000000000000" } ], - "routeProcessorAddr": "0x46B3fDF7b5CDe91Ac049936bF0bDb12c5d22202e", - "routeProcessorArgs": { - "tokenIn": "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", - "amountIn": "10000000000000000000", - "tokenOut": "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", - "amountOutMin": "10000000000000000000", - "to": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - "routeCode": "0x0301ffff0201f39Fd6e51aad88F6F4ce6aB8827279cffFb922660d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", - "value": "10000000000000000000", - "txdata": "0x2646478b000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf12700000000000000000000000000000000000000000000000008ac7230489e80000000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000002e0301ffff0201f39fd6e51aad88f6f4ce6ab8827279cfffb922660d500b1d8e8ef31e21c99d1db9a6444d3adf1270000000000000000000000000000000000000" + "routeProcessorAddr": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "tx": { + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "to": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "data": "0x2646478b000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000056bc75e2d631000000000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf12700000000000000000000000000000000000000000000000056bc75e2d63100000000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000002e0301ffff0201f39Fd6e51aad88F6F4ce6aB8827279cffFb922660d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270000000000000000000000000000000000000", + "value": "100000000000000000000" } -} +} \ No newline at end of file From e014acead6b715b6e1dac6757e0c1faab4f31bb1 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Wed, 7 Aug 2024 14:36:03 +0100 Subject: [PATCH 075/125] chore: v5 generate swaps script --- apps/web/test/swap/scripts/generate-swaps.ts | 42 +++++++++++++------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/apps/web/test/swap/scripts/generate-swaps.ts b/apps/web/test/swap/scripts/generate-swaps.ts index 7d035405a6..f8f033432c 100644 --- a/apps/web/test/swap/scripts/generate-swaps.ts +++ b/apps/web/test/swap/scripts/generate-swaps.ts @@ -1,8 +1,14 @@ import fs from 'fs' import { type UseTradeParams, tradeValidator02 } from '@sushiswap/react-query' import { ChainId } from 'sushi' -import { isRouteProcessor4ChainId } from 'sushi/config' +import { + MULTISIG_ADDRESS, + isMultisigChainId, + publicClientConfig, +} from 'sushi/config' import { Amount, Native, USDC, USDT, WBTC } from 'sushi/currency' +import { createPublicClient, stringify } from 'viem' +import { getBlockNumber } from 'viem/actions' import { isSwapApiEnabledChainId } from '../../../src/config' const RECIPIENT = '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266' @@ -51,13 +57,6 @@ const API_BASE_URL = process.env['NEXT_PUBLIC_API_BASE_URL'] || 'https://api.sushi.com' -function getApiVersion(chainId: ChainId) { - if (isRouteProcessor4ChainId(chainId)) { - return '/v4' - } - return '' -} - const getSwapApiResult = async ({ fromToken, toToken, @@ -66,9 +65,7 @@ const getSwapApiResult = async ({ slippagePercentage, source, }: TradeParams) => { - const params = new URL( - `${API_BASE_URL}/swap${getApiVersion(chainId)}/${chainId}`, - ) + const params = new URL(`${API_BASE_URL}/swap/v5/${chainId}`) params.searchParams.set( 'tokenIn', @@ -87,10 +84,22 @@ const getSwapApiResult = async ({ }`, ) params.searchParams.set('amount', `${amount?.quotient.toString()}`) - params.searchParams.set('maxPriceImpact', `${+slippagePercentage / 100}`) + params.searchParams.set('maxSlippage', `${+slippagePercentage / 100}`) params.searchParams.set('gasPrice', `${gasPrice}`) - params.searchParams.set('to', RECIPIENT) + params.searchParams.set('to', `${RECIPIENT}`) params.searchParams.set('preferSushi', 'true') + params.searchParams.set('enableFee', 'true') + params.searchParams.set( + 'feeReceiver', + isMultisigChainId(chainId) + ? MULTISIG_ADDRESS[chainId] + : '0xFF64C2d5e23e9c48e8b42a23dc70055EEC9ea098', + ) + params.searchParams.set('fee', '0.0025') + params.searchParams.set('feeBy', 'output') + params.searchParams.set('includeTransaction', 'true') + params.searchParams.set('includeRoute', 'true') + if (source !== undefined) params.searchParams.set('source', `${source}`) console.log(params.toString()) @@ -170,11 +179,16 @@ trades[`${chainId}-wrap`] = { } const main = async () => { + const blockNumber = await getBlockNumber( + createPublicClient(publicClientConfig[chainId]), + ) + console.log('Block number: ', blockNumber) + for (const [name, trade] of Object.entries(trades)) { const result = await getSwapApiResult(trade) fs.writeFileSync( `${MOCK_DIRECTORY}/${name}.json`, - JSON.stringify(result, null, 2), + stringify(result, null, 2), ) } } From 5f51791323449b7985c55483d9611d3da96e7ae2 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Wed, 7 Aug 2024 14:36:30 +0100 Subject: [PATCH 076/125] chore: update .env.test --- apps/web/.env.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web/.env.test b/apps/web/.env.test index b3a3893a98..b5f3d6095a 100644 --- a/apps/web/.env.test +++ b/apps/web/.env.test @@ -1,4 +1,4 @@ -ANVIL_BLOCK_NUMBER=47479278 +ANVIL_BLOCK_NUMBER=60301962 ANVIL_FORK_URL=https://polygon-mainnet.g.alchemy.com/v2/ ANVIL_PORT=8545 EDGE_CONFIG= From 10b79cb80d55732d3f8b93bac5d383c2629b2c74 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Wed, 7 Aug 2024 14:37:01 +0100 Subject: [PATCH 077/125] workflow: set to latest block --- .github/workflows/apps-web-e2e.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/apps-web-e2e.yml b/.github/workflows/apps-web-e2e.yml index 608d9be2f2..a49ed0fa06 100644 --- a/.github/workflows/apps-web-e2e.yml +++ b/.github/workflows/apps-web-e2e.yml @@ -30,7 +30,7 @@ jobs: timeout-minutes: 15 strategy: matrix: - block-number: [55359656] + block-number: [60301962] chain-id: [137] node-version: [20] pnpm-version: [9.4.0] From 697444a46e170152d8fe2bad31faa0f80b625e46 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Wed, 7 Aug 2024 14:37:13 +0100 Subject: [PATCH 078/125] chore: cleanup --- apis/router/src/create-swap-body.ts | 46 ------------------- .../react-query/src/hooks/trade/apiAdapter.ts | 3 -- .../src/hooks/trade/validator01.ts | 1 - .../src/hooks/trade/validator02.ts | 1 - 4 files changed, 51 deletions(-) diff --git a/apis/router/src/create-swap-body.ts b/apis/router/src/create-swap-body.ts index 4e08ed8ba4..f303fe7efa 100644 --- a/apis/router/src/create-swap-body.ts +++ b/apis/router/src/create-swap-body.ts @@ -56,51 +56,6 @@ class TokenConvertor { } } -// export function makeAPI02Object( -// route: MultiRoute, -// rpParams: RPParams | undefined, -// routeProcessorAddr: string, -// ) { -// if (route.status === RouteStatus.NoWay) return { status: RouteStatus.NoWay } -// const tokens = new TokenConvertor() -// route.legs.forEach((l) => { -// tokens.addToken(l.tokenFrom) -// tokens.addToken(l.tokenTo) -// }) -// const APIObj = { -// status: route.status, -// tokens: tokens.getTokenList(), -// tokenFrom: tokens.getTokenIndex(route.fromToken), -// tokenTo: tokens.getTokenIndex(route.toToken), - -// primaryPrice: route.primaryPrice, -// swapPrice: route.swapPrice, -// priceImpact: route.priceImpact, - -// amountIn: route.amountInBI.toString(), -// assumedAmountOut: route.amountOutBI.toString(), -// gasSpent: route.gasSpent, - -// route: route.legs.map((l) => makeAPI02Leg(l, tokens)), -// } as any -// if (rpParams !== undefined) { -// APIObj.routeProcessorAddr = routeProcessorAddr -// APIObj.routeProcessorArgs = { -// tokenIn: rpParams.tokenIn, -// amountIn: rpParams.amountIn.toString(), -// tokenOut: rpParams.tokenOut, -// amountOutMin: rpParams.amountOutMin.toString(), -// to: rpParams.to, -// routeCode: rpParams.routeCode, -// txdata: rpParams.data, -// } -// if (rpParams.value !== undefined) -// APIObj.routeProcessorArgs.value = rpParams.value.toString() -// } - -// return APIObj -// } - export function createSwapBody( route: MultiRoute, rpParams?: RPParams | undefined, @@ -157,7 +112,6 @@ export function createSwapBody( amountOutMin: rpParams.amountOutMin.toString(), to: rpParams.to, routeCode: rpParams.routeCode, - txdata: rpParams.data, value: rpParams.value !== undefined ? rpParams.value.toString() diff --git a/packages/react-query/src/hooks/trade/apiAdapter.ts b/packages/react-query/src/hooks/trade/apiAdapter.ts index 51b9b95b22..0c5aca8383 100644 --- a/packages/react-query/src/hooks/trade/apiAdapter.ts +++ b/packages/react-query/src/hooks/trade/apiAdapter.ts @@ -149,9 +149,6 @@ export function apiAdapter02To01( routeCode: res.routeProcessorArgs.routeCode, } : undefined, - txdata: res.routeProcessorArgs - ? res.routeProcessorArgs.txdata - : undefined, tx: res.tx ? res.tx : undefined, } } diff --git a/packages/react-query/src/hooks/trade/validator01.ts b/packages/react-query/src/hooks/trade/validator01.ts index 2fe12cd375..d3b00fae2d 100644 --- a/packages/react-query/src/hooks/trade/validator01.ts +++ b/packages/react-query/src/hooks/trade/validator01.ts @@ -69,5 +69,4 @@ export const tradeValidator01 = z.object({ value: z.coerce.bigint().optional(), }), ), - txdata: z.optional(z.string()), }) diff --git a/packages/react-query/src/hooks/trade/validator02.ts b/packages/react-query/src/hooks/trade/validator02.ts index a469fbac5c..eab32ea1ea 100644 --- a/packages/react-query/src/hooks/trade/validator02.ts +++ b/packages/react-query/src/hooks/trade/validator02.ts @@ -48,7 +48,6 @@ const routeExistValidator = z.object({ to: z.string(), routeCode: z.string(), value: z.string().optional(), - txdata: z.string(), }) .optional(), From 4128e8b88b8eeb45728ab68def659e96cdf42c51 Mon Sep 17 00:00:00 2001 From: matthewlilley Date: Wed, 7 Aug 2024 13:38:22 +0000 Subject: [PATCH 079/125] chore: lint --- apps/web/test/swap/mock/137-native-to-usdc.json | 2 +- apps/web/test/swap/mock/137-native-to-usdt.json | 2 +- apps/web/test/swap/mock/137-native-to-wbtc.json | 2 +- apps/web/test/swap/mock/137-unwrap.json | 2 +- apps/web/test/swap/mock/137-usdc-to-native.json | 2 +- apps/web/test/swap/mock/137-usdc-to-usdt.json | 2 +- apps/web/test/swap/mock/137-usdt-to-native.json | 2 +- apps/web/test/swap/mock/137-wrap.json | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/web/test/swap/mock/137-native-to-usdc.json b/apps/web/test/swap/mock/137-native-to-usdc.json index 9a0b7585fb..c1aea6916a 100644 --- a/apps/web/test/swap/mock/137-native-to-usdc.json +++ b/apps/web/test/swap/mock/137-native-to-usdc.json @@ -170,4 +170,4 @@ "data": "0x2646478b000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000056bc75e2d631000000000000000000000000000003c499c542cef5e3811e1192ce70d8cc03d5c33590000000000000000000000000000000000000000000000000000000002696b78000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000022e0301ffff0201f2614A233c7C3e7f08b1F887Ba133a13f1eb2c550d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270010d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270045eb80121988C9CFD08db3b5793c2C6782271dC9474925101f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55aaaa01562A0460FE6cfc2E610AE5596c5b4ACe94d97C5601f39Fd6e51aad88F6F4ce6aB8827279cffFb92266555501f1A12338D39Fc085D8631E1A745B5116BC9b2A3201f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55ffff0055FF76BFFC3Cdd9D5FdbBC2ece4528ECcE45047e01f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55000bb801c2132D05D31c914a87C6611C10748AEb04B58e8F01ffff01498d5cdcC5667b21210b49442Bf2D8792527194d00f39Fd6e51aad88F6F4ce6aB8827279cffFb92266017ceB23fD6bC0adD59E62ac25578270cFf1b9f61902b6da0034965ba0ac2451A34a0471F04CCa3F990b8dea2700f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55000bb8ffff01333923EC5bb34bf25468d77C641771e86Ee7bfCf01f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55018f3Cf7ad23Cd3CaDbD9735AFf958023239c6A06301ffff014646E8A5e1d14E2DA01577822D6346c7883C689000f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55012791Bca1f2de4661ED88A30C99A7a9449Aa8417401ffff0100604DCc4463D6c39D957BC25C7b6683dDD2Ba9001f39Fd6e51aad88F6F4ce6aB8827279cffFb92266000000000000000000000000000000000000", "value": "100000000000000000000" } -} \ No newline at end of file +} diff --git a/apps/web/test/swap/mock/137-native-to-usdt.json b/apps/web/test/swap/mock/137-native-to-usdt.json index fd5b3a660f..a558e966b8 100644 --- a/apps/web/test/swap/mock/137-native-to-usdt.json +++ b/apps/web/test/swap/mock/137-native-to-usdt.json @@ -153,4 +153,4 @@ "data": "0x2646478b000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000056bc75e2d63100000000000000000000000000000c2132d05d31c914a87c6611c10748aeb04b58e8f00000000000000000000000000000000000000000000000000000000026928a5000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001e90301ffff0201f2614A233c7C3e7f08b1F887Ba133a13f1eb2c550d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270010d500B1d8E8eF31E21C99d1Db9A6444d3ADf12700461470121988C9CFD08db3b5793c2C6782271dC9474925101f2614A233c7C3e7f08b1F887Ba133a13f1eb2c554a5201562A0460FE6cfc2E610AE5596c5b4ACe94d97C5601f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55a2e801f1A12338D39Fc085D8631E1A745B5116BC9b2A3201c2755915a85C6f6c1C0F3a86ac8C058F11Caa9C9ffff0055FF76BFFC3Cdd9D5FdbBC2ece4528ECcE45047e01f39Fd6e51aad88F6F4ce6aB8827279cffFb92266000bb8013c499c542cEF5E3811e1192ce70d8cC03d5c335901ffff01498d5cdcC5667b21210b49442Bf2D8792527194d01f39Fd6e51aad88F6F4ce6aB8827279cffFb92266012791Bca1f2de4661ED88A30C99A7a9449Aa841740203e401EF69494EeA0ecBFbbFa1cfd5386268a562bc875F01c2755915a85C6f6c1C0F3a86ac8C058F11Caa9C9ffff018CFaab34f5159abf9C35587AC40d09a05dC9476501f39Fd6e51aad88F6F4ce6aB8827279cffFb92266047ceB23fD6bC0adD59E62ac25578270cFf1b9f61900c2755915a85C6f6c1C0F3a86ac8C058F11Caa9C901f39Fd6e51aad88F6F4ce6aB8827279cffFb92266000bb80000000000000000000000000000000000000000000000", "value": "100000000000000000000" } -} \ No newline at end of file +} diff --git a/apps/web/test/swap/mock/137-native-to-wbtc.json b/apps/web/test/swap/mock/137-native-to-wbtc.json index 28f3693a71..7b38d72155 100644 --- a/apps/web/test/swap/mock/137-native-to-wbtc.json +++ b/apps/web/test/swap/mock/137-native-to-wbtc.json @@ -175,4 +175,4 @@ "data": "0x6678ec1f000000000000000000000000850a57630a2012b2494779fbc86bbc24f2a7baef00000000000000000000000000000000000000000000000000000000000000af000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000056bc75e2d631000000000000000000000000000001bfd67037b42cf73acf2047067bd4f2c47d9bfd600000000000000000000000000000000000000000000000000000000000112f1000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002470301ffff0201f2614A233c7C3e7f08b1F887Ba133a13f1eb2c550d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270010d500B1d8E8eF31E21C99d1Db9A6444d3ADf127004051f008531c4e29491fE6e5e87AF6054FC20FcCf0b429001f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55000bb81f590121988C9CFD08db3b5793c2C6782271dC9474925101f2614A233c7C3e7f08b1F887Ba133a13f1eb2c554a6b00c4e595acDD7d12feC385E5dA5D43160e8A0bAC0E01E62Ec2e799305E0D367b0Cc3ee2CdA135bF89816000bb8ffff01f1A12338D39Fc085D8631E1A745B5116BC9b2A3201E62Ec2e799305E0D367b0Cc3ee2CdA135bF89816012791Bca1f2de4661ED88A30C99A7a9449Aa84174042aad00D02b870c556480491c70AaF98C297fddd93F6f5C00f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55000bb8cccd01F88dE8Aaa065EcBF9a3C67f7A93b4c82595f6D6F00f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55800c01EF69494EeA0ecBFbbFa1cfd5386268a562bc875F01E62Ec2e799305E0D367b0Cc3ee2CdA135bF89816ffff014646E8A5e1d14E2DA01577822D6346c7883C689001f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55018f3Cf7ad23Cd3CaDbD9735AFf958023239c6A06301ffff01333923EC5bb34bf25468d77C641771e86Ee7bfCf00E62Ec2e799305E0D367b0Cc3ee2CdA135bF89816047ceB23fD6bC0adD59E62ac25578270cFf1b9f61900E62Ec2e799305E0D367b0Cc3ee2CdA135bF8981600f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55000bb800000000000000000000000000000000000000000000000000", "value": "100000000000000000000" } -} \ No newline at end of file +} diff --git a/apps/web/test/swap/mock/137-unwrap.json b/apps/web/test/swap/mock/137-unwrap.json index 8cc6f508a0..5b40721973 100644 --- a/apps/web/test/swap/mock/137-unwrap.json +++ b/apps/web/test/swap/mock/137-unwrap.json @@ -40,4 +40,4 @@ "to": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", "data": "0x2646478b0000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf12700000000000000000000000000000000000000000000000056bc75e2d63100000000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000056bc75e2d63100000000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000002e020d500B1d8E8eF31E21C99d1Db9A6444d3ADf127001ffff0200f39Fd6e51aad88F6F4ce6aB8827279cffFb92266000000000000000000000000000000000000" } -} \ No newline at end of file +} diff --git a/apps/web/test/swap/mock/137-usdc-to-native.json b/apps/web/test/swap/mock/137-usdc-to-native.json index b289a3a97e..b266244c30 100644 --- a/apps/web/test/swap/mock/137-usdc-to-native.json +++ b/apps/web/test/swap/mock/137-usdc-to-native.json @@ -186,4 +186,4 @@ "to": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", "data": "0x2646478b0000000000000000000000003c499c542cef5e3811e1192ce70d8cc03d5c335900000000000000000000000000000000000000000000000000000000000f4240000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee00000000000000000000000000000000000000000000000021e479dd325a1647000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000026d023c499c542cEF5E3811e1192ce70d8cC03d5c33590255550100604DCc4463D6c39D957BC25C7b6683dDD2Ba9000f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55ffff01498d5cdcC5667b21210b49442Bf2D8792527194d01f2614A233c7C3e7f08b1F887Ba133a13f1eb2c5501c2132D05D31c914a87C6611C10748AEb04B58e8F03bfff01dB0101bE2132408e65B30246aa662e4D6f49599c00f2614A233c7C3e7f08b1F887Ba133a13f1eb2c557fff017e5Fc5677Dfb16dFBC250AFf8F90E6ceF743Ca0100f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55ffff00a543Ba3fd79a03788e5521a0Ce48B3F2Bf93b2c1017d88D931504D04BFBEE6F9745297A93063CAb24c000bb804D6DF932A45C0f255f85145f286eA0b292B21C90B007d88D931504D04BFBEE6F9745297A93063CAb24c00f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55000bb8018f3Cf7ad23Cd3CaDbD9735AFf958023239c6A06301ffff01e58517662569c742388b90dC5461F7DBBBD8aE5800f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55012791Bca1f2de4661ED88A30C99A7a9449Aa8417402400001934F3F8749164111f0386eCE4f4965a687E576d500f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55ffff01EF69494EeA0ecBFbbFa1cfd5386268a562bc875F01f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55017ceB23fD6bC0adD59E62ac25578270cFf1b9f61901ffff01f1A12338D39Fc085D8631E1A745B5116BC9b2A3200f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55010d500B1d8E8eF31E21C99d1Db9A6444d3ADf127001ffff0200f39Fd6e51aad88F6F4ce6aB8827279cffFb9226600000000000000000000000000000000000000" } -} \ No newline at end of file +} diff --git a/apps/web/test/swap/mock/137-usdc-to-usdt.json b/apps/web/test/swap/mock/137-usdc-to-usdt.json index d167803b68..5bb85740d5 100644 --- a/apps/web/test/swap/mock/137-usdc-to-usdt.json +++ b/apps/web/test/swap/mock/137-usdc-to-usdt.json @@ -40,4 +40,4 @@ "to": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", "data": "0x2646478b0000000000000000000000003c499c542cef5e3811e1192ce70d8cc03d5c335900000000000000000000000000000000000000000000000000000000000f4240000000000000000000000000c2132d05d31c914a87c6611c10748aeb04b58e8f00000000000000000000000000000000000000000000000000000000000f2c51000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000042023c499c542cEF5E3811e1192ce70d8cC03d5c335901ffff01498d5cdcC5667b21210b49442Bf2D8792527194d01f39Fd6e51aad88F6F4ce6aB8827279cffFb92266000000000000000000000000000000000000000000000000000000000000" } -} \ No newline at end of file +} diff --git a/apps/web/test/swap/mock/137-usdt-to-native.json b/apps/web/test/swap/mock/137-usdt-to-native.json index e67945443d..ad4bca46fb 100644 --- a/apps/web/test/swap/mock/137-usdt-to-native.json +++ b/apps/web/test/swap/mock/137-usdt-to-native.json @@ -175,4 +175,4 @@ "to": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", "data": "0x2646478b000000000000000000000000c2132d05d31c914a87c6611c10748aeb04b58e8f00000000000000000000000000000000000000000000000000000000000f4240000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee00000000000000000000000000000000000000000000000021e68cb83039009e000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000024102c2132D05D31c914a87C6611C10748AEb04B58e8F04955501dB0101bE2132408e65B30246aa662e4D6f49599c00f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55999901498d5cdcC5667b21210b49442Bf2D8792527194d00f2614A233c7C3e7f08b1F887Ba133a13f1eb2c557fff017e5Fc5677Dfb16dFBC250AFf8F90E6ceF743Ca0100f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55ffff00a543Ba3fd79a03788e5521a0Ce48B3F2Bf93b2c1017d88D931504D04BFBEE6F9745297A93063CAb24c000bb804D6DF932A45C0f255f85145f286eA0b292B21C90B007d88D931504D04BFBEE6F9745297A93063CAb24c00f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55000bb8018f3Cf7ad23Cd3CaDbD9735AFf958023239c6A06301ffff01e58517662569c742388b90dC5461F7DBBBD8aE5800f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55013c499c542cEF5E3811e1192ce70d8cC03d5c335901ffff0100604DCc4463D6c39D957BC25C7b6683dDD2Ba9000f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55012791Bca1f2de4661ED88A30C99A7a9449Aa8417401ffff01EF69494EeA0ecBFbbFa1cfd5386268a562bc875F01f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55017ceB23fD6bC0adD59E62ac25578270cFf1b9f61901ffff01f1A12338D39Fc085D8631E1A745B5116BC9b2A3200f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55010d500B1d8E8eF31E21C99d1Db9A6444d3ADf127001ffff0200f39Fd6e51aad88F6F4ce6aB8827279cffFb9226600000000000000000000000000000000000000000000000000000000000000" } -} \ No newline at end of file +} diff --git a/apps/web/test/swap/mock/137-wrap.json b/apps/web/test/swap/mock/137-wrap.json index 19f946d646..c9a5d5931e 100644 --- a/apps/web/test/swap/mock/137-wrap.json +++ b/apps/web/test/swap/mock/137-wrap.json @@ -41,4 +41,4 @@ "data": "0x2646478b000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000056bc75e2d631000000000000000000000000000000d500b1d8e8ef31e21c99d1db9a6444d3adf12700000000000000000000000000000000000000000000000056bc75e2d63100000000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000002e0301ffff0201f39Fd6e51aad88F6F4ce6aB8827279cffFb922660d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270000000000000000000000000000000000000", "value": "100000000000000000000" } -} \ No newline at end of file +} From d4e4412773c2e06b0604c46bd39776d8c983658b Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Wed, 7 Aug 2024 15:34:13 +0100 Subject: [PATCH 080/125] fix: mock swap api regex --- apps/web/test/helpers/swap.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/apps/web/test/helpers/swap.ts b/apps/web/test/helpers/swap.ts index fb81ce5af5..5a5cab3de3 100644 --- a/apps/web/test/helpers/swap.ts +++ b/apps/web/test/helpers/swap.ts @@ -300,8 +300,11 @@ export class SwapPage extends BaseActions { } async mockSwapApi(jsonFile: string) { - await this.page.route('https://api.sushi.com/swap/**/*', (route) => { - return route.fulfill({ path: jsonFile }) - }) + await this.page.route( + /^(https:\/\/api\.sushi\.com|https:\/\/staging\.sushi\.com|http:\/\/127\.0\.0\.1:4505)\/swap\/v\d\/\d+(.*)$/gm, + (route) => { + return route.fulfill({ path: jsonFile }) + }, + ) } } From 99fb312f48a6878ae06752446b4d99af9ddef1c8 Mon Sep 17 00:00:00 2001 From: 0xMasayoshi <0xMasayoshi@protonmail.com> Date: Wed, 7 Aug 2024 23:06:10 +0700 Subject: [PATCH 081/125] fix: isLsd --- packages/sushi/src/router/router.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/sushi/src/router/router.ts b/packages/sushi/src/router/router.ts index cf9e9d208f..f9d9828783 100644 --- a/packages/sushi/src/router/router.ts +++ b/packages/sushi/src/router/router.ts @@ -11,6 +11,7 @@ import { routeProcessorAbi } from '../abi/routeProcessorAbi.js' import { ChainId } from '../chain/index.js' import { ADDITIONAL_BASES } from '../config/additional-bases.js' import { BASES_TO_CHECK_TRADES_AGAINST } from '../config/bases-to-check-trades-against.js' +import { LSDS } from '../config/lsds.js' import { STABLES } from '../config/stables.js' import { Native, WNATIVE, WNATIVE_ADDRESS } from '../currency/index.js' import { Token, type Type } from '../currency/index.js' @@ -127,10 +128,10 @@ export const isLsd = ({ fromToken, toToken, }: { fromToken: Type; toToken: Type }) => { - const fromTokenIsLsd = STABLES[fromToken.chainId].some((t: Token) => + const fromTokenIsLsd = LSDS[fromToken.chainId].some((t: Token) => t.equals(fromToken), ) - const toTokenIsLsd = STABLES[toToken.chainId].some((t: Token) => + const toTokenIsLsd = LSDS[toToken.chainId].some((t: Token) => t.equals(toToken), ) return ( From 6dda8a482fd04b29d8c9e03c55197c2eacc381a7 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Wed, 7 Aug 2024 17:29:07 +0100 Subject: [PATCH 082/125] chore: export swap api api base url from sushi config --- .../lib/swap/cross-chain/actions/getTrade.ts | 4 ++-- apps/web/test/helpers/swap.ts | 3 ++- apps/web/test/playwright.config.ts | 3 ++- apps/web/test/swap/scripts/generate-swaps.ts | 9 ++------ .../react-query/src/hooks/prices/usePrices.ts | 8 +++---- .../react-query/src/hooks/trade/useTrade.ts | 23 ++----------------- packages/sushi/src/config/api.ts | 4 ++++ packages/sushi/src/config/index.ts | 1 + turbo.json | 3 +-- 9 files changed, 19 insertions(+), 39 deletions(-) create mode 100644 packages/sushi/src/config/api.ts diff --git a/apps/web/src/lib/swap/cross-chain/actions/getTrade.ts b/apps/web/src/lib/swap/cross-chain/actions/getTrade.ts index 930aabcd27..bf9b7af629 100644 --- a/apps/web/src/lib/swap/cross-chain/actions/getTrade.ts +++ b/apps/web/src/lib/swap/cross-chain/actions/getTrade.ts @@ -1,10 +1,10 @@ import { - TRADE_API_BASE_URL, UseTradeParams, // getTradeQueryApiVersion, tradeValidator02, } from '@sushiswap/react-query' import { RouteStatus } from 'sushi/tines' +import { API_BASE_URL } from 'sushi/config' import { Address } from 'viem' import { z } from 'zod' @@ -38,7 +38,7 @@ export const getTrade = async ({ recipient, source, }: GetTrade) => { - const params = new URL(`${TRADE_API_BASE_URL}/swap/v4/${chainId}`) + const params = new URL(`${API_BASE_URL}/swap/v4/${chainId}`) params.searchParams.set('chainId', `${chainId}`) params.searchParams.set('tokenIn', `${fromToken}`) params.searchParams.set('tokenOut', `${toToken}`) diff --git a/apps/web/test/helpers/swap.ts b/apps/web/test/helpers/swap.ts index 5a5cab3de3..364f99fcfb 100644 --- a/apps/web/test/helpers/swap.ts +++ b/apps/web/test/helpers/swap.ts @@ -1,4 +1,5 @@ import { Page, expect } from '@playwright/test' +import { API_BASE_URL } from 'sushi/config' import { Native, Type } from 'sushi/currency' import { zeroAddress } from 'viem' import { BaseActions } from './base' // Adjust the import path as necessary @@ -301,7 +302,7 @@ export class SwapPage extends BaseActions { async mockSwapApi(jsonFile: string) { await this.page.route( - /^(https:\/\/api\.sushi\.com|https:\/\/staging\.sushi\.com|http:\/\/127\.0\.0\.1:4505)\/swap\/v\d\/\d+(.*)$/gm, + `${API_BASE_URL}/swap/v5/${this.chainId}*`, (route) => { return route.fulfill({ path: jsonFile }) }, diff --git a/apps/web/test/playwright.config.ts b/apps/web/test/playwright.config.ts index 0f42ccddae..c925c9e3c1 100644 --- a/apps/web/test/playwright.config.ts +++ b/apps/web/test/playwright.config.ts @@ -18,7 +18,8 @@ const baseURL = `http://localhost:${PORT}` * See https://playwright.dev/docs/test-configuration. */ const config: PlaywrightTestConfig = { - quiet: !!process.env.CI, + // quiet: !!process.env.CI, + quiet: true, testMatch: [ // 'pool.test.ts', 'simple.test.ts', diff --git a/apps/web/test/swap/scripts/generate-swaps.ts b/apps/web/test/swap/scripts/generate-swaps.ts index f8f033432c..57b320a66f 100644 --- a/apps/web/test/swap/scripts/generate-swaps.ts +++ b/apps/web/test/swap/scripts/generate-swaps.ts @@ -1,7 +1,8 @@ import fs from 'fs' import { type UseTradeParams, tradeValidator02 } from '@sushiswap/react-query' -import { ChainId } from 'sushi' +import { ChainId } from 'sushi/chain' import { + API_BASE_URL, MULTISIG_ADDRESS, isMultisigChainId, publicClientConfig, @@ -51,12 +52,6 @@ if (!fs.existsSync(MOCK_DIRECTORY)) { fs.rmSync(MOCK_DIRECTORY, { recursive: true }) fs.mkdirSync(MOCK_DIRECTORY) -// ! COPIED FROM packages/react-query/src/hooks/trade/useTrade.ts -const API_BASE_URL = - process.env['API_BASE_URL'] || - process.env['NEXT_PUBLIC_API_BASE_URL'] || - 'https://api.sushi.com' - const getSwapApiResult = async ({ fromToken, toToken, diff --git a/packages/react-query/src/hooks/prices/usePrices.ts b/packages/react-query/src/hooks/prices/usePrices.ts index 323204c22a..24499b3440 100644 --- a/packages/react-query/src/hooks/prices/usePrices.ts +++ b/packages/react-query/src/hooks/prices/usePrices.ts @@ -1,5 +1,6 @@ import { useQuery } from '@tanstack/react-query' import ms from 'ms' +import { API_BASE_URL } from 'sushi/config' import { withoutScientificNotation } from 'sushi/format' import { Fraction } from 'sushi/math' import { getAddress, isAddress, parseUnits } from 'viem' @@ -9,15 +10,12 @@ interface UsePrices { enabled?: boolean } -const BASE_URL = - process.env['NEXT_PUBLIC_API_BASE_URL'] || 'https://api.sushi.com' - export const usePrices = ({ chainId, enabled = true }: UsePrices) => { return useQuery({ - queryKey: [`${BASE_URL}/price/v1/${chainId}`], + queryKey: [`${API_BASE_URL}/price/v1/${chainId}`], queryFn: async () => { const data: Record = await fetch( - `${BASE_URL}/price/v1/${chainId}`, + `${API_BASE_URL}/price/v1/${chainId}`, ).then((response) => response.json()) return Object.entries(data).reduce>( (acc, [address, _price]) => { diff --git a/packages/react-query/src/hooks/trade/useTrade.ts b/packages/react-query/src/hooks/trade/useTrade.ts index ad7cea74bc..d5d5428231 100644 --- a/packages/react-query/src/hooks/trade/useTrade.ts +++ b/packages/react-query/src/hooks/trade/useTrade.ts @@ -6,11 +6,10 @@ import { import { useQuery } from '@tanstack/react-query' import { useCallback, useMemo } from 'react' import { slippageAmount } from 'sushi/calculate' -import { ChainId } from 'sushi/chain' import { + API_BASE_URL, MULTISIG_ADDRESS, isMultisigChainId, - isRouteProcessor4ChainId, isRouteProcessor5ChainId, isWNativeSupported, } from 'sushi/config' @@ -23,20 +22,6 @@ import { apiAdapter02To01 } from './apiAdapter' import type { UseTradeParams, UseTradeQuerySelect } from './types' import { tradeValidator02 } from './validator02' -export const TRADE_API_BASE_URL = - process.env['API_BASE_URL'] || - process.env['NEXT_PUBLIC_API_BASE_URL'] || - 'https://api.sushi.com/swap' - -export function getTradeQueryApiVersion(chainId: ChainId) { - if (isRouteProcessor5ChainId(chainId)) { - return '/v5' - } else if (isRouteProcessor4ChainId(chainId)) { - return '/v4' - } - return '' -} - export const useTradeQuery = ( { chainId, @@ -67,11 +52,7 @@ export const useTradeQuery = ( }, ], queryFn: async () => { - const params = new URL( - `${TRADE_API_BASE_URL}/swap${getTradeQueryApiVersion( - chainId, - )}/${chainId}`, - ) + const params = new URL(`${API_BASE_URL}/swap/v5/${chainId}`) // params.searchParams.set('chainId', `${chainId}`) params.searchParams.set( 'tokenIn', diff --git a/packages/sushi/src/config/api.ts b/packages/sushi/src/config/api.ts new file mode 100644 index 0000000000..ef6cfaff98 --- /dev/null +++ b/packages/sushi/src/config/api.ts @@ -0,0 +1,4 @@ +export const API_BASE_URL = + process.env['API_BASE_URL'] || + process.env['NEXT_PUBLIC_API_BASE_URL'] || + 'https://api.sushi.com' diff --git a/packages/sushi/src/config/index.ts b/packages/sushi/src/config/index.ts index 5a779fb49f..d2b3a73e2b 100644 --- a/packages/sushi/src/config/index.ts +++ b/packages/sushi/src/config/index.ts @@ -1,5 +1,6 @@ export * from './additional-bases.js' export * from './angle.js' +export * from './api.js' export * from './bases-to-check-trades-against.js' export * from './bentobox.js' export * from './custom-bases.js' diff --git a/turbo.json b/turbo.json index 036cb40718..de4d3e720b 100644 --- a/turbo.json +++ b/turbo.json @@ -73,14 +73,13 @@ "dependsOn": ["^build", "generate"], "env": [ "ALCHEMY_ID", + "API_BASE_URL", "APP_ENV", "DATABASE_URL", "DRPC_ID", "EDGE_CONFIG", "RSK_ID", - "POOLS_API_V0_BASE_URL", "REDIS_URL", - "SWAP_API_V0_BASE_URL", "TOKENS_API_V0_BASE_URL", "STRAPI_API_URL", "VERCEL_ENV", From 4eb4604debf6dadd155345601ca5870c0a6b9509 Mon Sep 17 00:00:00 2001 From: 0xMasayoshi <0xMasayoshi@protonmail.com> Date: Thu, 8 Aug 2024 00:33:23 +0700 Subject: [PATCH 083/125] chore: update LSDS --- packages/sushi/src/config/lsds.ts | 364 +++++++++++++++++++++++++++++- 1 file changed, 352 insertions(+), 12 deletions(-) diff --git a/packages/sushi/src/config/lsds.ts b/packages/sushi/src/config/lsds.ts index 72791b138f..2689acfe62 100644 --- a/packages/sushi/src/config/lsds.ts +++ b/packages/sushi/src/config/lsds.ts @@ -2,14 +2,145 @@ import { ChainId } from '../chain/index.js' import { Token } from '../currency/token.js' export const LSDS = { - [ChainId.ARBITRUM]: [], + [ChainId.ARBITRUM]: [ + new Token({ + chainId: ChainId.ARBITRUM, + address: '0x5979D7b546E38E414F7E9822514be443A4800529', + decimals: 18, + symbol: 'wstETH', + name: 'Wrapped Lido Staked ETH', + }), + new Token({ + chainId: ChainId.ARBITRUM, + address: '0x178412e79c25968a32e89b11f63B33F733770c2A', + decimals: 18, + symbol: 'frxETH', + name: 'Frax Ether', + }), + new Token({ + chainId: ChainId.ARBITRUM, + address: '0x95aB45875cFFdba1E5f451B950bC2E42c0053f39', + decimals: 18, + symbol: 'sfrxETH', + name: 'Staked Frax Ether', + }), + new Token({ + chainId: ChainId.ARBITRUM, + address: '0xEC70Dcb4A1EFa46b8F2D97C310C9c4790ba5ffA8', + decimals: 18, + symbol: 'rETH', + name: 'Rocket Pool ETH', + }), + new Token({ + chainId: ChainId.ARBITRUM, + address: '0x1DEBd73E752bEaF79865Fd6446b0c970EaE7732f', + decimals: 18, + symbol: 'cbETH', + name: 'Coinbase cbETH', + }), + new Token({ + chainId: ChainId.ARBITRUM, + address: '0x2416092f143378750bb29b79eD961ab195CcEea5', + decimals: 18, + symbol: 'ezETH', + name: 'Renzo Restaked ETH', + }), + new Token({ + chainId: ChainId.ARBITRUM, + address: '0x35751007a407ca6FEFfE80b3cB397736D2cf4dbe', + decimals: 18, + symbol: 'weETH', + name: 'Wrapped eETH', + }), + ], [ChainId.ARBITRUM_NOVA]: [], [ChainId.AVALANCHE]: [], - [ChainId.BASE]: [], + [ChainId.BASE]: [ + new Token({ + chainId: ChainId.BASE, + address: '0xB6fe221Fe9EeF5aBa221c348bA20A1Bf5e73624c', + decimals: 18, + symbol: 'wstETH', + name: 'Wrapped Lido Staked ETH', + }), + new Token({ + chainId: ChainId.BASE, + address: '0x53878B874283351D26d206FA512aEcE1Bef6C0dD', + decimals: 18, + symbol: 'rETH', + name: 'Rocket Pool ETH', + }), + new Token({ + chainId: ChainId.BASE, + address: '0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cf0DEc22', + decimals: 18, + symbol: 'cbETH', + name: 'Coinbase cbETH', + }), + new Token({ + chainId: ChainId.BASE, + address: '0x2416092f143378750bb29b79eD961ab195CcEea5', + decimals: 18, + symbol: 'ezETH', + name: 'Renzo Restaked ETH', + }), + new Token({ + chainId: ChainId.BASE, + address: '0x04C0599Ae5A44757c0af6F9eC3b93da8976c150A', + decimals: 18, + symbol: 'weETH', + name: 'Wrapped eETH', + }), + ], + [ChainId.BLAST]: [ + new Token({ + chainId: ChainId.BLAST, + address: '0x2416092f143378750bb29b79eD961ab195CcEea5', + decimals: 18, + symbol: 'ezETH', + name: 'Renzo Restaked ETH', + }), + new Token({ + chainId: ChainId.BLAST, + address: '0x04C0599Ae5A44757c0af6F9eC3b93da8976c150A', + decimals: 18, + symbol: 'weETH', + name: 'Wrapped eETH', + }), + ], [ChainId.BOBA]: [], [ChainId.BOBA_AVAX]: [], [ChainId.BOBA_BNB]: [], - [ChainId.BSC]: [], + [ChainId.BSC]: [ + new Token({ + chainId: ChainId.BSC, + address: '0x64048A7eEcF3a2F1BA9e144aAc3D7dB6e58F555e', + decimals: 18, + symbol: 'frxETH', + name: 'Frax Ether', + }), + new Token({ + chainId: ChainId.BSC, + address: '0x3Cd55356433C89E50DC51aB07EE0fa0A95623D53', + decimals: 18, + symbol: 'sfrxETH', + name: 'Staked Frax Ether', + }), + new Token({ + chainId: ChainId.BSC, + address: '0x2416092f143378750bb29b79eD961ab195CcEea5', + decimals: 18, + symbol: 'ezETH', + name: 'Renzo Restaked ETH', + }), + new Token({ + chainId: ChainId.BSC, + address: '0x04C0599Ae5A44757c0af6F9eC3b93da8976c150A', + decimals: 18, + symbol: 'weETH', + name: 'Wrapped eETH', + }), + ], [ChainId.BTTC]: [], [ChainId.CELO]: [], [ChainId.ETHEREUM]: [ @@ -17,9 +148,16 @@ export const LSDS = { chainId: ChainId.ETHEREUM, address: '0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84', decimals: 18, - symbol: 'StETH', + symbol: 'stETH', name: 'Lido Staked ETH', }), + new Token({ + chainId: ChainId.ETHEREUM, + address: '0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0', + decimals: 18, + symbol: 'wstETH', + name: 'Wrapped Lido Staked ETH', + }), new Token({ chainId: ChainId.ETHEREUM, address: '0xae78736cd615f374d3085123a210448e74fc6393', @@ -27,8 +165,86 @@ export const LSDS = { symbol: 'rETH', name: 'Rocket Pool ETH', }), + new Token({ + chainId: ChainId.ETHEREUM, + address: '0x35fA164735182de50811E8e2E824cFb9B6118ac2', + decimals: 18, + symbol: 'eETH', + name: 'ether.fi ETH', + }), + new Token({ + chainId: ChainId.ETHEREUM, + address: '0xCd5fE23C85820F7B72D0926FC9b05b43E359b7ee', + decimals: 18, + symbol: 'weETH', + name: 'Wrapped eETH', + }), + new Token({ + chainId: ChainId.ETHEREUM, + address: '0xBe9895146f7AF43049ca1c1AE358B0541Ea49704', + decimals: 18, + symbol: 'cbETH', + name: 'Coinbase cbETH', + }), + new Token({ + chainId: ChainId.ETHEREUM, + address: '0xf951E335afb289353dc249e82926178EaC7DEd78', + decimals: 18, + symbol: 'swETH', + name: 'Swell swETH', + }), + new Token({ + chainId: ChainId.ETHEREUM, + address: '0x5E8422345238F34275888049021821E8E08CAa1f', + decimals: 18, + symbol: 'frxETH', + name: 'Frax Ether', + }), + new Token({ + chainId: ChainId.ETHEREUM, + address: '0xac3E018457B222d93114458476f3E3416Abbe38F', + decimals: 18, + symbol: 'sfrxETH', + name: 'Staked Frax Ether', + }), + new Token({ + chainId: ChainId.ETHEREUM, + address: '0xA35b1B31Ce002FBF2058D22F30f95D405200A15b', + decimals: 18, + symbol: 'ETHx', + name: 'Stader ETHx', + }), + new Token({ + chainId: ChainId.ETHEREUM, + address: '0xd5F7838F5C461fefF7FE49ea5ebaF7728bB0ADfa', + decimals: 18, + symbol: 'mETH', + name: 'Mantle Staked Ether', + }), + new Token({ + chainId: ChainId.ETHEREUM, + address: '0x2416092f143378750bb29b79eD961ab195CcEea5', + decimals: 18, + symbol: 'ezETH', + name: 'Renzo Restaked ETH', + }), + ], + [ChainId.FANTOM]: [ + new Token({ + chainId: ChainId.FANTOM, + address: '0x9E73F99EE061C8807F69f9c6CCc44ea3d8c373ee', + decimals: 18, + symbol: 'frxETH', + name: 'Frax Ether', + }), + new Token({ + chainId: ChainId.FANTOM, + address: '0xb90CCD563918fF900928dc529aA01046795ccb4A', + decimals: 18, + symbol: 'sfrxETH', + name: 'Staked Frax Ether', + }), ], - [ChainId.FANTOM]: [], [ChainId.FILECOIN]: [], [ChainId.FUSE]: [], [ChainId.GNOSIS]: [], @@ -36,21 +252,145 @@ export const LSDS = { [ChainId.HAQQ]: [], [ChainId.HECO]: [], [ChainId.KAVA]: [], - [ChainId.LINEA]: [], + [ChainId.LINEA]: [ + new Token({ + chainId: ChainId.LINEA, + address: '0x2416092f143378750bb29b79eD961ab195CcEea5', + decimals: 18, + symbol: 'ezETH', + name: 'Renzo Restaked ETH', + }), + new Token({ + chainId: ChainId.LINEA, + address: '0x1Bf74C010E6320bab11e2e5A532b5AC15e0b8aA6', + decimals: 18, + symbol: 'weETH', + name: 'Wrapped eETH', + }), + ], [ChainId.METIS]: [], - [ChainId.MOONBEAM]: [], + [ChainId.MOONBEAM]: [ + new Token({ + chainId: ChainId.MOONBEAM, + address: '0x82bbd1b6f6De2B7bb63D3e1546e6b1553508BE99', + decimals: 18, + symbol: 'frxETH', + name: 'Frax Ether', + }), + new Token({ + chainId: ChainId.MOONBEAM, + address: '0xecf91116348aF1cfFe335e9807f0051332BE128D', + decimals: 18, + symbol: 'sfrxETH', + name: 'Staked Frax Ether', + }), + ], [ChainId.MOONRIVER]: [], [ChainId.OKEX]: [], - [ChainId.OPTIMISM]: [], - [ChainId.POLYGON]: [], - [ChainId.POLYGON_ZKEVM]: [], - [ChainId.SCROLL]: [], + [ChainId.OPTIMISM]: [ + new Token({ + chainId: ChainId.OPTIMISM, + address: '0x1F32b1c2345538c0c6f582fCB022739c4A194Ebb', + decimals: 18, + symbol: 'wstETH', + name: 'Wrapped Lido Staked ETH', + }), + new Token({ + chainId: ChainId.OPTIMISM, + address: '0x6806411765Af15Bddd26f8f544A34cC40cb9838B', + decimals: 18, + symbol: 'frxETH', + name: 'Frax Ether', + }), + new Token({ + chainId: ChainId.OPTIMISM, + address: '0x484c2D6e3cDd945a8B2DF735e079178C1036578c', + decimals: 18, + symbol: 'sfrxETH', + name: 'Staked Frax Ether', + }), + new Token({ + chainId: ChainId.OPTIMISM, + address: '0x9Bcef72be871e61ED4fBbc7630889beE758eb81D', + decimals: 18, + symbol: 'rETH', + name: 'Rocket Pool ETH', + }), + new Token({ + chainId: ChainId.OPTIMISM, + address: '0xadDb6A0412DE1BA0F936DCaeb8Aaa24578dcF3B2', + decimals: 18, + symbol: 'cbETH', + name: 'Coinbase cbETH', + }), + new Token({ + chainId: ChainId.OPTIMISM, + address: '0x5A7fACB970D094B6C7FF1df0eA68D99E6e73CBFF', + decimals: 18, + symbol: 'weETH', + name: 'Wrapped eETH', + }), + ], + [ChainId.POLYGON]: [ + new Token({ + chainId: ChainId.POLYGON, + address: '0xEe327F889d5947c1dc1934Bb208a1E792F953E96', + decimals: 18, + symbol: 'frxETH', + name: 'Frax Ether', + }), + new Token({ + chainId: ChainId.POLYGON, + address: '0x6d1FdBB266fCc09A16a22016369210A15bb95761', + decimals: 18, + symbol: 'sfrxETH', + name: 'Staked Frax Ether', + }), + new Token({ + chainId: ChainId.POLYGON, + address: '0x0266F4F08D82372CF0FcbCCc0Ff74309089c74d1', + decimals: 18, + symbol: 'rETH', + name: 'Rocket Pool ETH', + }), + ], + [ChainId.POLYGON_ZKEVM]: [ + new Token({ + chainId: ChainId.POLYGON_ZKEVM, + address: '0xb23C20EFcE6e24Acca0Cef9B7B7aA196b84EC942', + decimals: 18, + symbol: 'rETH', + name: 'Rocket Pool ETH', + }), + ], + [ChainId.SCROLL]: [ + new Token({ + chainId: ChainId.SCROLL, + address: '0xf610A9dfB7C89644979b4A0f27063E9e7d7Cda32', + decimals: 18, + symbol: 'wstETH', + name: 'Wrapped Lido Staked ETH', + }), + new Token({ + chainId: ChainId.SCROLL, + address: '0x53878B874283351D26d206FA512aEcE1Bef6C0dD', + decimals: 18, + symbol: 'rETH', + name: 'Rocket Pool ETH', + }), + new Token({ + chainId: ChainId.SCROLL, + address: '0x01f0a31698C4d065659b9bdC21B3610292a1c506', + decimals: 18, + symbol: 'weETH', + name: 'Wrapped eETH', + }), + ], [ChainId.TELOS]: [], [ChainId.THUNDERCORE]: [], [ChainId.CORE]: [], [ChainId.ZETACHAIN]: [], [ChainId.CRONOS]: [], - [ChainId.BLAST]: [], [ChainId.SKALE_EUROPA]: [], [ChainId.ROOTSTOCK]: [], [ChainId.PALM]: [], From 1079e5445116fdf42c43817b351b55954793c5a2 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Wed, 7 Aug 2024 18:37:00 +0100 Subject: [PATCH 084/125] fix: most tests --- apps/web/package.json | 4 +- apps/web/test/global.setup.ts | 13 +- apps/web/test/intercept-anvil.ts | 2 +- apps/web/test/playwright.config.ts | 2 +- .../test/swap/mock/137-native-to-usdc.json | 212 ++- .../test/swap/mock/137-native-to-usdt.json | 90 +- .../test/swap/mock/137-native-to-wbtc.json | 124 +- .../test/swap/mock/137-usdc-to-native.json | 213 +-- apps/web/test/swap/mock/137-usdc-to-usdt.json | 10 +- .../test/swap/mock/137-usdt-to-native.json | 205 ++- apps/web/test/swap/simple.test.ts | 10 +- pnpm-lock.yaml | 1191 +++++++++++------ 12 files changed, 1347 insertions(+), 729 deletions(-) diff --git a/apps/web/package.json b/apps/web/package.json index c44f416efa..5d0fae548f 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -116,14 +116,14 @@ "@types/lodash.once": "4.1.9", "@types/lodash.uniqby": "^4.7.9", "@types/lodash.zip": "4.2.9", - "@types/node": "20", + "@types/node": "22", "@types/react": "18.2.14", "@types/react-dom": "18.2.6", "@types/react-slider": "1.3.1", "@types/react-virtualized-auto-sizer": "1.0.1", "@types/react-window": "1.8.5", "@types/tryghost__content-api": "1.3.12", - "@viem/anvil": "0.0.7", + "@viem/anvil": "0.0.10", "autoprefixer": "10.4.14", "eslint-config-next": "14.2.3", "eslint-config-sushi": "workspace:*", diff --git a/apps/web/test/global.setup.ts b/apps/web/test/global.setup.ts index 8d0f7e598c..10b892e479 100644 --- a/apps/web/test/global.setup.ts +++ b/apps/web/test/global.setup.ts @@ -1,6 +1,8 @@ import { type FullConfig } from '@playwright/test' import { startProxy } from '@viem/anvil' - +// import 'core-js/proposals/promise-with-resolvers.js' +// import { createServer } from 'prool' +// import { anvil } from 'prool/instances' export default async function globalSetup(_config: FullConfig) { // console.log('globalSetup') @@ -11,8 +13,11 @@ export default async function globalSetup(_config: FullConfig) { startTimeout: 120_000, }, }) + process.on('SIGTERM', shutdown) - process.on('SIGTERM', async () => { - await shutdown() - }) + // const server = createServer({ + // instance: anvil(), + // }) + // server.start() + // process.on('SIGTERM', server.stop) } diff --git a/apps/web/test/intercept-anvil.ts b/apps/web/test/intercept-anvil.ts index 970b9da6d8..c7711d6d77 100644 --- a/apps/web/test/intercept-anvil.ts +++ b/apps/web/test/intercept-anvil.ts @@ -22,7 +22,7 @@ export const interceptAnvil = async (page: Page, next: NextFixture) => { next.onFetch((request) => { if (request.url === 'http://127.0.0.1:8545/') { // console.log( - // `intercept anvil request url ${request.url} and re-write to ${url}` + // `intercept anvil request url ${request.url} and re-write to ${url}`, // ) return fetch(url, request) } diff --git a/apps/web/test/playwright.config.ts b/apps/web/test/playwright.config.ts index c925c9e3c1..47462d8db6 100644 --- a/apps/web/test/playwright.config.ts +++ b/apps/web/test/playwright.config.ts @@ -21,7 +21,7 @@ const config: PlaywrightTestConfig = { // quiet: !!process.env.CI, quiet: true, testMatch: [ - // 'pool.test.ts', + 'pool.test.ts', 'simple.test.ts', // 'smart.test.ts', // 'cross-chain.test.ts', diff --git a/apps/web/test/swap/mock/137-native-to-usdc.json b/apps/web/test/swap/mock/137-native-to-usdc.json index 9a0b7585fb..a466862518 100644 --- a/apps/web/test/swap/mock/137-native-to-usdc.json +++ b/apps/web/test/swap/mock/137-native-to-usdc.json @@ -13,6 +13,12 @@ "name": "Wrapped Matic", "decimals": 18 }, + { + "address": "0x1BFD67037B42Cf73acF2047067bd4F2C47D9BfD6", + "symbol": "WBTC", + "name": "(PoS) Wrapped BTC", + "decimals": 8 + }, { "address": "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", "symbol": "USDC", @@ -31,6 +37,12 @@ "name": "Wrapped Ether", "decimals": 18 }, + { + "address": "0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063", + "symbol": "DAI", + "name": "(PoS) Dai Stablecoin", + "decimals": 18 + }, { "address": "0xc2132D05D31c914a87C6611C10748AEb04B58e8F", "symbol": "USDT", @@ -38,19 +50,19 @@ "decimals": 6 }, { - "address": "0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063", - "symbol": "DAI", - "name": "(PoS) Dai Stablecoin", + "address": "0xD6DF932A45C0f255f85145f286eA0b292B21C90B", + "symbol": "AAVE", + "name": "Aave (PoS)", "decimals": 18 } ], "tokenFrom": 0, - "tokenTo": 3, - "swapPrice": 4.0666556999999975e-13, - "priceImpact": 0.0031127967403997703, + "tokenTo": 4, + "swapPrice": 3.936412599999997e-13, + "priceImpact": 0.00307893059735187, "amountIn": "100000000000000000000", - "assumedAmountOut": "40666557", - "gasSpent": 940000, + "assumedAmountOut": "39364126", + "gasSpent": 1780000, "route": [ { "poolAddress": "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", @@ -63,16 +75,49 @@ "assumedAmountIn": "100000000000000065536", "assumedAmountOut": "100000000000000065536" }, + { + "poolAddress": "0x8531c4e29491fE6e5e87AF6054FC20FcCf0b4290", + "poolType": "Classic", + "poolName": "SushiSwapV2 0.3%", + "poolFee": 0.003, + "tokenFrom": 1, + "tokenTo": 2, + "share": 0.01, + "assumedAmountIn": "999465934233616256", + "assumedAmountOut": "703" + }, + { + "poolAddress": "0xcd353F79d9FADe311fC3119B841e1f456b54e858", + "poolType": "Classic", + "poolName": "SushiSwapV2 0.3%", + "poolFee": 0.003, + "tokenFrom": 1, + "tokenTo": 3, + "share": 0.1, + "assumedAmountIn": "10000511719163408384", + "assumedAmountOut": "3934810" + }, + { + "poolAddress": "0x934F3F8749164111f0386eCE4f4965a687E576d5", + "poolType": "Concentrated", + "poolName": "SushiSwapV3 0.01%", + "poolFee": 0.0001, + "tokenFrom": 1, + "tokenTo": 3, + "share": 0.01, + "assumedAmountIn": "999527221287858944", + "assumedAmountOut": "395060" + }, { "poolAddress": "0x21988C9CFD08db3b5793c2C6782271dC94749251", "poolType": "Concentrated", "poolName": "SushiSwapV3 0.05%", "poolFee": 0.0005, "tokenFrom": 1, - "tokenTo": 2, - "share": 0.37, - "assumedAmountIn": "37000076295109509120", - "assumedAmountOut": "15073271" + "tokenTo": 3, + "share": 0.1, + "assumedAmountIn": "9999842636731854848", + "assumedAmountOut": "3941366" }, { "poolAddress": "0x562A0460FE6cfc2E610AE5596c5b4ACe94d97C56", @@ -80,10 +125,10 @@ "poolName": "SushiSwapV3 0.3%", "poolFee": 0.003, "tokenFrom": 1, - "tokenTo": 3, - "share": 0.42, - "assumedAmountIn": "41999949136593698816", - "assumedAmountOut": "17058670" + "tokenTo": 4, + "share": 0.11, + "assumedAmountIn": "10999954685274845184", + "assumedAmountOut": "4328813" }, { "poolAddress": "0xf1A12338D39Fc085D8631E1A745B5116BC9b2A32", @@ -91,10 +136,21 @@ "poolName": "SushiSwapV3 0.05%", "poolFee": 0.0005, "tokenFrom": 1, - "tokenTo": 4, - "share": 0.07, - "assumedAmountIn": "6999991522765619200", - "assumedAmountOut": "1151083310209743" + "tokenTo": 5, + "share": 0.57, + "assumedAmountIn": "57000944614719766528", + "assumedAmountOut": "9395308392488682" + }, + { + "poolAddress": "0x8929D3FEa77398F64448c85015633c2d6472fB29", + "poolType": "Classic", + "poolName": "SushiSwapV2 0.3%", + "poolFee": 0.003, + "tokenFrom": 1, + "tokenTo": 6, + "share": 0.04, + "assumedAmountIn": "3999901275435480064", + "assumedAmountOut": "1575180682506899712" }, { "poolAddress": "0x55FF76BFFC3Cdd9D5FdbBC2ece4528ECcE45047e", @@ -102,43 +158,98 @@ "poolName": "SushiSwapV2 0.3%", "poolFee": 0.003, "tokenFrom": 1, - "tokenTo": 5, - "share": 0.14, - "assumedAmountIn": "13999983045531238400", - "assumedAmountOut": "5688102" + "tokenTo": 7, + "share": 0.04, + "assumedAmountIn": "3999901275435479552", + "assumedAmountOut": "1573399" + }, + { + "poolAddress": "0xdB0101bE2132408e65B30246aa662e4D6f49599c", + "poolType": "Concentrated", + "poolName": "SushiSwapV3 0.3%", + "poolFee": 0.003, + "tokenFrom": 1, + "tokenTo": 7, + "share": 0.01, + "assumedAmountIn": "999990577504156672", + "assumedAmountOut": "393652" + }, + { + "poolAddress": "0x7d88D931504D04BFBEE6F9745297A93063CAb24c", + "poolType": "Classic", + "poolName": "SushiSwapV2 0.3%", + "poolFee": 0.003, + "tokenFrom": 1, + "tokenTo": 8, + "share": 0.01, + "assumedAmountIn": "999960060213583360", + "assumedAmountOut": "3919590599626827" + }, + { + "poolAddress": "0x3E9a0586088caEb2aDFf32B0C06CfA44151c7a5B", + "poolType": "Classic", + "poolName": "SushiSwapV2 0.3%", + "poolFee": 0.003, + "tokenFrom": 8, + "tokenTo": 3, + "share": 1, + "assumedAmountIn": "3919590599626827", + "assumedAmountOut": "394963" }, { "poolAddress": "0x498d5cdcC5667b21210b49442Bf2D8792527194d", "poolType": "Concentrated", "poolName": "SushiSwapV3 0.01%", "poolFee": 0.0001, - "tokenFrom": 5, - "tokenTo": 3, + "tokenFrom": 7, + "tokenTo": 4, "share": 1, - "assumedAmountIn": "5688102", - "assumedAmountOut": "5690476" + "assumedAmountIn": "1967051", + "assumedAmountOut": "1967468" }, { "poolAddress": "0x34965ba0ac2451A34a0471F04CCa3F990b8dea27", "poolType": "Classic", "poolName": "SushiSwapV2 0.3%", "poolFee": 0.003, - "tokenFrom": 4, - "tokenTo": 2, - "share": 0.7142811661133296, - "assumedAmountIn": "822189818431648", - "assumedAmountOut": "2032825" + "tokenFrom": 5, + "tokenTo": 3, + "share": 0.01754072839828819, + "assumedAmountIn": "164867698960280", + "assumedAmountOut": "393616" + }, + { + "poolAddress": "0xEF69494EeA0ecBFbbFa1cfd5386268a562bc875F", + "poolType": "Concentrated", + "poolName": "SushiSwapV3 0.01%", + "poolFee": 0.0001, + "tokenFrom": 5, + "tokenTo": 3, + "share": 0.017546879579339942, + "assumedAmountIn": "164791571090687", + "assumedAmountOut": "394300" + }, + { + "poolAddress": "0x1b0585Fc8195fc04a46A365E670024Dfb63a960C", + "poolType": "Concentrated", + "poolName": "SushiSwapV3 0.3%", + "poolFee": 0.003, + "tokenFrom": 5, + "tokenTo": 3, + "share": 0.9122736549028722, + "assumedAmountIn": "8571108867418034", + "assumedAmountOut": "20467330" }, { "poolAddress": "0x333923EC5bb34bf25468d77C641771e86Ee7bfCf", "poolType": "Concentrated", "poolName": "SushiSwapV3 0.01%", "poolFee": 0.0001, - "tokenFrom": 4, + "tokenFrom": 5, "tokenTo": 6, - "share": 0.2857188338866703, - "assumedAmountIn": "328893491778095", - "assumedAmountOut": "813735244605366656" + "share": 0.052638737119499714, + "assumedAmountIn": "494540255019682", + "assumedAmountOut": "1182480915219130624" }, { "poolAddress": "0x4646E8A5e1d14E2DA01577822D6346c7883C6890", @@ -146,28 +257,39 @@ "poolName": "SushiSwapV3 0.01%", "poolFee": 0.0001, "tokenFrom": 6, - "tokenTo": 2, + "tokenTo": 3, + "share": 1, + "assumedAmountIn": "2757661597726030336", + "assumedAmountOut": "2757425" + }, + { + "poolAddress": "0xD02b870c556480491c70AaF98C297fddd93F6f5C", + "poolType": "Classic", + "poolName": "SushiSwapV2 0.3%", + "poolFee": 0.003, + "tokenFrom": 2, + "tokenTo": 3, "share": 1, - "assumedAmountIn": "813735244605366656", - "assumedAmountOut": "813679" + "assumedAmountIn": "703", + "assumedAmountOut": "393626" }, { "poolAddress": "0x00604DCc4463D6c39D957BC25C7b6683dDD2Ba90", "poolType": "Concentrated", "poolName": "SushiSwapV3 0.01%", "poolFee": 0.0001, - "tokenFrom": 2, - "tokenTo": 3, + "tokenFrom": 3, + "tokenTo": 4, "share": 1, - "assumedAmountIn": "17919775", - "assumedAmountOut": "17917411" + "assumedAmountIn": "33072496", + "assumedAmountOut": "33067845" } ], "routeProcessorAddr": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", "tx": { "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", "to": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", - "data": "0x2646478b000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000056bc75e2d631000000000000000000000000000003c499c542cef5e3811e1192ce70d8cc03d5c33590000000000000000000000000000000000000000000000000000000002696b78000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000022e0301ffff0201f2614A233c7C3e7f08b1F887Ba133a13f1eb2c550d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270010d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270045eb80121988C9CFD08db3b5793c2C6782271dC9474925101f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55aaaa01562A0460FE6cfc2E610AE5596c5b4ACe94d97C5601f39Fd6e51aad88F6F4ce6aB8827279cffFb92266555501f1A12338D39Fc085D8631E1A745B5116BC9b2A3201f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55ffff0055FF76BFFC3Cdd9D5FdbBC2ece4528ECcE45047e01f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55000bb801c2132D05D31c914a87C6611C10748AEb04B58e8F01ffff01498d5cdcC5667b21210b49442Bf2D8792527194d00f39Fd6e51aad88F6F4ce6aB8827279cffFb92266017ceB23fD6bC0adD59E62ac25578270cFf1b9f61902b6da0034965ba0ac2451A34a0471F04CCa3F990b8dea2700f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55000bb8ffff01333923EC5bb34bf25468d77C641771e86Ee7bfCf01f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55018f3Cf7ad23Cd3CaDbD9735AFf958023239c6A06301ffff014646E8A5e1d14E2DA01577822D6346c7883C689000f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55012791Bca1f2de4661ED88A30C99A7a9449Aa8417401ffff0100604DCc4463D6c39D957BC25C7b6683dDD2Ba9001f39Fd6e51aad88F6F4ce6aB8827279cffFb92266000000000000000000000000000000000000", + "data": "0x2646478b000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000056bc75e2d631000000000000000000000000000003c499c542cef5e3811e1192ce70d8cc03d5c3359000000000000000000000000000000000000000000000000000000000255a549000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000041e0301ffff0201f2614A233c7C3e7f08b1F887Ba133a13f1eb2c550d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270010d500B1d8E8eF31E21C99d1Db9A6444d3ADf12700a028f008531c4e29491fE6e5e87AF6054FC20FcCf0b429001D02b870c556480491c70AaF98C297fddd93F6f5C000bb819dc00cd353F79d9FADe311fC3119B841e1f456b54e85801f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55000bb802e001934F3F8749164111f0386eCE4f4965a687E576d501f2614A233c7C3e7f08b1F887Ba133a13f1eb2c551d170121988C9CFD08db3b5793c2C6782271dC9474925101f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55241a01562A0460FE6cfc2E610AE5596c5b4ACe94d97C5601f39Fd6e51aad88F6F4ce6aB8827279cffFb92266d9ca01f1A12338D39Fc085D8631E1A745B5116BC9b2A3201f2614A233c7C3e7f08b1F887Ba133a13f1eb2c556666008929D3FEa77398F64448c85015633c2d6472fB2901f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55000bb8aaaa0055FF76BFFC3Cdd9D5FdbBC2ece4528ECcE45047e01f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55000bb8800001dB0101bE2132408e65B30246aa662e4D6f49599c01f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55ffff007d88D931504D04BFBEE6F9745297A93063CAb24c013E9a0586088caEb2aDFf32B0C06CfA44151c7a5B000bb804D6DF932A45C0f255f85145f286eA0b292B21C90B003E9a0586088caEb2aDFf32B0C06CfA44151c7a5B00f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55000bb801c2132D05D31c914a87C6611C10748AEb04B58e8F01ffff01498d5cdcC5667b21210b49442Bf2D8792527194d00f39Fd6e51aad88F6F4ce6aB8827279cffFb92266017ceB23fD6bC0adD59E62ac25578270cFf1b9f61904047e0034965ba0ac2451A34a0471F04CCa3F990b8dea2700f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55000bb8049201EF69494EeA0ecBFbbFa1cfd5386268a562bc875F00f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55f208011b0585Fc8195fc04a46A365E670024Dfb63a960C00f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55ffff01333923EC5bb34bf25468d77C641771e86Ee7bfCf01f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55018f3Cf7ad23Cd3CaDbD9735AFf958023239c6A06301ffff014646E8A5e1d14E2DA01577822D6346c7883C689000f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55041BFD67037B42Cf73acF2047067bd4F2C47D9BfD600D02b870c556480491c70AaF98C297fddd93F6f5C01f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55000bb8012791Bca1f2de4661ED88A30C99A7a9449Aa8417401ffff0100604DCc4463D6c39D957BC25C7b6683dDD2Ba9001f39Fd6e51aad88F6F4ce6aB8827279cffFb922660000", "value": "100000000000000000000" } } \ No newline at end of file diff --git a/apps/web/test/swap/mock/137-native-to-usdt.json b/apps/web/test/swap/mock/137-native-to-usdt.json index fd5b3a660f..68ae14204b 100644 --- a/apps/web/test/swap/mock/137-native-to-usdt.json +++ b/apps/web/test/swap/mock/137-native-to-usdt.json @@ -40,11 +40,11 @@ ], "tokenFrom": 0, "tokenTo": 5, - "swapPrice": 4.0649363999999977e-13, - "priceImpact": 0.004636128886240876, + "swapPrice": 3.9333128e-13, + "priceImpact": 0.0025206838646716356, "amountIn": "100000000000000000000", - "assumedAmountOut": "40649364", - "gasSpent": 830000, + "assumedAmountOut": "39333128", + "gasSpent": 870000, "route": [ { "poolAddress": "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", @@ -54,8 +54,8 @@ "tokenFrom": 0, "tokenTo": 1, "share": 1, - "assumedAmountIn": "100000000000000065536", - "assumedAmountOut": "100000000000000065536" + "assumedAmountIn": "100000000000000000000", + "assumedAmountOut": "100000000000000000000" }, { "poolAddress": "0x21988C9CFD08db3b5793c2C6782271dC94749251", @@ -64,9 +64,9 @@ "poolFee": 0.0005, "tokenFrom": 1, "tokenTo": 2, - "share": 0.38, - "assumedAmountIn": "37999542229343125504", - "assumedAmountOut": "15479573" + "share": 0.08333333333333334, + "assumedAmountIn": "8332951857785915392", + "assumedAmountOut": "3285297" }, { "poolAddress": "0x562A0460FE6cfc2E610AE5596c5b4ACe94d97C56", @@ -75,9 +75,9 @@ "poolFee": 0.003, "tokenFrom": 1, "tokenTo": 3, - "share": 0.18, - "assumedAmountIn": "17999858236736385024", - "assumedAmountOut": "7316487" + "share": 0.08333333333333337, + "assumedAmountIn": "8333749490063500288", + "assumedAmountOut": "3279868" }, { "poolAddress": "0xf1A12338D39Fc085D8631E1A745B5116BC9b2A32", @@ -86,9 +86,9 @@ "poolFee": 0.0005, "tokenFrom": 1, "tokenTo": 4, - "share": 0.28, - "assumedAmountIn": "28000320484666552320", - "assumedAmountOut": "4604083697194467" + "share": 0.6666666666666666, + "assumedAmountIn": "66666638921720463360", + "assumedAmountOut": "10988139608767242" }, { "poolAddress": "0x55FF76BFFC3Cdd9D5FdbBC2ece4528ECcE45047e", @@ -97,31 +97,42 @@ "poolFee": 0.003, "tokenFrom": 1, "tokenTo": 5, - "share": 0.16, - "assumedAmountIn": "16000279049253998592", - "assumedAmountOut": "6500259" + "share": 0.16666666666666663, + "assumedAmountIn": "16666659730430115840", + "assumedAmountOut": "6552534" }, { - "poolAddress": "0x498d5cdcC5667b21210b49442Bf2D8792527194d", + "poolAddress": "0x1b0585Fc8195fc04a46A365E670024Dfb63a960C", "poolType": "Concentrated", - "poolName": "SushiSwapV3 0.01%", - "poolFee": 0.0001, - "tokenFrom": 3, + "poolName": "SushiSwapV3 0.3%", + "poolFee": 0.003, + "tokenFrom": 4, + "tokenTo": 2, + "share": 0.4999667979551232, + "assumedAmountIn": "5493650633726386", + "assumedAmountOut": "13119452" + }, + { + "poolAddress": "0xc2755915a85C6f6c1C0F3a86ac8C058F11Caa9C9", + "poolType": "Classic", + "poolName": "SushiSwapV2 0.3%", + "poolFee": 0.003, + "tokenFrom": 4, "tokenTo": 5, - "share": 1, - "assumedAmountIn": "7316487", - "assumedAmountOut": "7311963" + "share": 0.5000332020448768, + "assumedAmountIn": "5494488975040856", + "assumedAmountOut": "13103473" }, { - "poolAddress": "0xEF69494EeA0ecBFbbFa1cfd5386268a562bc875F", + "poolAddress": "0x498d5cdcC5667b21210b49442Bf2D8792527194d", "poolType": "Concentrated", "poolName": "SushiSwapV3 0.01%", "poolFee": 0.0001, - "tokenFrom": 2, - "tokenTo": 4, - "share": 0.015195761677617376, - "assumedAmountIn": "235258", - "assumedAmountOut": "95384524746537" + "tokenFrom": 3, + "tokenTo": 5, + "share": 1, + "assumedAmountIn": "3279868", + "assumedAmountOut": "3278515" }, { "poolAddress": "0x8CFaab34f5159abf9C35587AC40d09a05dC94765", @@ -130,27 +141,16 @@ "poolFee": 0.0001, "tokenFrom": 2, "tokenTo": 5, - "share": 0.9848042383223826, - "assumedAmountIn": "15244315", - "assumedAmountOut": "15236047" - }, - { - "poolAddress": "0xc2755915a85C6f6c1C0F3a86ac8C058F11Caa9C9", - "poolType": "Classic", - "poolName": "SushiSwapV2 0.3%", - "poolFee": 0.003, - "tokenFrom": 4, - "tokenTo": 5, "share": 1, - "assumedAmountIn": "4699468221941004", - "assumedAmountOut": "11601095" + "assumedAmountIn": "16404749", + "assumedAmountOut": "16398606" } ], "routeProcessorAddr": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", "tx": { "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", "to": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", - "data": "0x2646478b000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000056bc75e2d63100000000000000000000000000000c2132d05d31c914a87c6611c10748aeb04b58e8f00000000000000000000000000000000000000000000000000000000026928a5000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001e90301ffff0201f2614A233c7C3e7f08b1F887Ba133a13f1eb2c550d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270010d500B1d8E8eF31E21C99d1Db9A6444d3ADf12700461470121988C9CFD08db3b5793c2C6782271dC9474925101f2614A233c7C3e7f08b1F887Ba133a13f1eb2c554a5201562A0460FE6cfc2E610AE5596c5b4ACe94d97C5601f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55a2e801f1A12338D39Fc085D8631E1A745B5116BC9b2A3201c2755915a85C6f6c1C0F3a86ac8C058F11Caa9C9ffff0055FF76BFFC3Cdd9D5FdbBC2ece4528ECcE45047e01f39Fd6e51aad88F6F4ce6aB8827279cffFb92266000bb8013c499c542cEF5E3811e1192ce70d8cC03d5c335901ffff01498d5cdcC5667b21210b49442Bf2D8792527194d01f39Fd6e51aad88F6F4ce6aB8827279cffFb92266012791Bca1f2de4661ED88A30C99A7a9449Aa841740203e401EF69494EeA0ecBFbbFa1cfd5386268a562bc875F01c2755915a85C6f6c1C0F3a86ac8C058F11Caa9C9ffff018CFaab34f5159abf9C35587AC40d09a05dC9476501f39Fd6e51aad88F6F4ce6aB8827279cffFb92266047ceB23fD6bC0adD59E62ac25578270cFf1b9f61900c2755915a85C6f6c1C0F3a86ac8C058F11Caa9C901f39Fd6e51aad88F6F4ce6aB8827279cffFb92266000bb80000000000000000000000000000000000000000000000", + "data": "0x2646478b000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000056bc75e2d63100000000000000000000000000000c2132d05d31c914a87c6611c10748aeb04b58e8f0000000000000000000000000000000000000000000000000000000002552cce000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001ec0301ffff0201f2614A233c7C3e7f08b1F887Ba133a13f1eb2c550d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270010d500B1d8E8eF31E21C99d1Db9A6444d3ADf12700415550121988C9CFD08db3b5793c2C6782271dC9474925101f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55174601562A0460FE6cfc2E610AE5596c5b4ACe94d97C5601f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55cccc01f1A12338D39Fc085D8631E1A745B5116BC9b2A3201f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55ffff0055FF76BFFC3Cdd9D5FdbBC2ece4528ECcE45047e01f39Fd6e51aad88F6F4ce6aB8827279cffFb92266000bb8017ceB23fD6bC0adD59E62ac25578270cFf1b9f619027ffd011b0585Fc8195fc04a46A365E670024Dfb63a960C00f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55ffff00c2755915a85C6f6c1C0F3a86ac8C058F11Caa9C901f39Fd6e51aad88F6F4ce6aB8827279cffFb92266000bb8013c499c542cEF5E3811e1192ce70d8cC03d5c335901ffff01498d5cdcC5667b21210b49442Bf2D8792527194d01f39Fd6e51aad88F6F4ce6aB8827279cffFb92266012791Bca1f2de4661ED88A30C99A7a9449Aa8417401ffff018CFaab34f5159abf9C35587AC40d09a05dC9476501f39Fd6e51aad88F6F4ce6aB8827279cffFb922660000000000000000000000000000000000000000", "value": "100000000000000000000" } } \ No newline at end of file diff --git a/apps/web/test/swap/mock/137-native-to-wbtc.json b/apps/web/test/swap/mock/137-native-to-wbtc.json index 28f3693a71..fbaf7e525e 100644 --- a/apps/web/test/swap/mock/137-native-to-wbtc.json +++ b/apps/web/test/swap/mock/137-native-to-wbtc.json @@ -32,19 +32,19 @@ "decimals": 18 }, { - "address": "0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063", - "symbol": "DAI", - "name": "(PoS) Dai Stablecoin", + "address": "0xD6DF932A45C0f255f85145f286eA0b292B21C90B", + "symbol": "AAVE", + "name": "Aave (PoS)", "decimals": 18 } ], "tokenFrom": 0, "tokenTo": 2, - "swapPrice": 7.0738999999999955e-16, - "priceImpact": 0.005572786531761298, + "swapPrice": 7.022399999999996e-16, + "priceImpact": 0.003766530494777931, "amountIn": "100000000000000000000", - "assumedAmountOut": "70739", - "gasSpent": 950000, + "assumedAmountOut": "70224", + "gasSpent": 730000, "route": [ { "poolAddress": "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", @@ -66,29 +66,29 @@ "tokenTo": 2, "share": 0.02, "assumedAmountIn": "2000457770656902144", - "assumedAmountOut": "1416" + "assumedAmountOut": "1406" }, { - "poolAddress": "0x21988C9CFD08db3b5793c2C6782271dC94749251", + "poolAddress": "0x934F3F8749164111f0386eCE4f4965a687E576d5", "poolType": "Concentrated", - "poolName": "SushiSwapV3 0.05%", - "poolFee": 0.0005, + "poolName": "SushiSwapV3 0.01%", + "poolFee": 0.0001, "tokenFrom": 1, "tokenTo": 3, - "share": 0.12, - "assumedAmountIn": "12000401714968776704", - "assumedAmountOut": "4895627" + "share": 0.01, + "assumedAmountIn": "1000407320537584128", + "assumedAmountOut": "395406" }, { - "poolAddress": "0xc4e595acDD7d12feC385E5dA5D43160e8A0bAC0E", - "poolType": "Classic", - "poolName": "SushiSwapV2 0.3%", - "poolFee": 0.003, + "poolAddress": "0x21988C9CFD08db3b5793c2C6782271dC94749251", + "poolType": "Concentrated", + "poolName": "SushiSwapV3 0.05%", + "poolFee": 0.0005, "tokenFrom": 1, - "tokenTo": 4, - "share": 0.25, - "assumedAmountIn": "24999917997090816000", - "assumedAmountOut": "4109533463103143" + "tokenTo": 3, + "share": 0.02, + "assumedAmountIn": "1999631208694534656", + "assumedAmountOut": "789187" }, { "poolAddress": "0xf1A12338D39Fc085D8631E1A745B5116BC9b2A32", @@ -97,64 +97,31 @@ "poolFee": 0.0005, "tokenFrom": 1, "tokenTo": 4, - "share": 0.61, - "assumedAmountIn": "60999222517283569664", - "assumedAmountOut": "10029028996212864" + "share": 0.94, + "assumedAmountIn": "93999280040187707392", + "assumedAmountOut": "15491815128014434" }, { - "poolAddress": "0xD02b870c556480491c70AaF98C297fddd93F6f5C", + "poolAddress": "0x7d88D931504D04BFBEE6F9745297A93063CAb24c", "poolType": "Classic", "poolName": "SushiSwapV2 0.3%", "poolFee": 0.003, - "tokenFrom": 3, - "tokenTo": 2, - "share": 0.1667040252283369, - "assumedAmountIn": "816124", - "assumedAmountOut": "1421" - }, - { - "poolAddress": "0xF88dE8Aaa065EcBF9a3C67f7A93b4c82595f6D6F", - "poolType": "Concentrated", - "poolName": "SushiSwapV3 0.3%", - "poolFee": 0.003, - "tokenFrom": 3, - "tokenTo": 2, - "share": 0.6666479818920626, - "assumedAmountIn": "3263664", - "assumedAmountOut": "5676" - }, - { - "poolAddress": "0xEF69494EeA0ecBFbbFa1cfd5386268a562bc875F", - "poolType": "Concentrated", - "poolName": "SushiSwapV3 0.01%", - "poolFee": 0.0001, - "tokenFrom": 3, - "tokenTo": 4, - "share": 0.08335667373140918, - "assumedAmountIn": "408075", - "assumedAmountOut": "165260487355010" - }, - { - "poolAddress": "0x4646E8A5e1d14E2DA01577822D6346c7883C6890", - "poolType": "Concentrated", - "poolName": "SushiSwapV3 0.01%", - "poolFee": 0.0001, - "tokenFrom": 3, + "tokenFrom": 1, "tokenTo": 5, - "share": 0.08329131914819138, - "assumedAmountIn": "407764", - "assumedAmountOut": "407710272319493824" + "share": 0.01, + "assumedAmountIn": "1000223659923341312", + "assumedAmountOut": "3920622964805685" }, { - "poolAddress": "0x333923EC5bb34bf25468d77C641771e86Ee7bfCf", - "poolType": "Concentrated", - "poolName": "SushiSwapV3 0.01%", - "poolFee": 0.0001, + "poolAddress": "0x3E9a0586088caEb2aDFf32B0C06CfA44151c7a5B", + "poolType": "Classic", + "poolName": "SushiSwapV2 0.3%", + "poolFee": 0.003, "tokenFrom": 5, - "tokenTo": 4, + "tokenTo": 3, "share": 1, - "assumedAmountIn": "407710272319493824", - "assumedAmountOut": "164483051446041" + "assumedAmountIn": "3920622964805685", + "assumedAmountOut": "395067" }, { "poolAddress": "0xE62Ec2e799305E0D367b0Cc3ee2CdA135bF89816", @@ -164,15 +131,26 @@ "tokenFrom": 4, "tokenTo": 2, "share": 1, - "assumedAmountIn": "14468305998117060", - "assumedAmountOut": "62226" + "assumedAmountIn": "15491815128014434", + "assumedAmountOut": "66007" + }, + { + "poolAddress": "0xF88dE8Aaa065EcBF9a3C67f7A93b4c82595f6D6F", + "poolType": "Concentrated", + "poolName": "SushiSwapV3 0.3%", + "poolFee": 0.003, + "tokenFrom": 3, + "tokenTo": 2, + "share": 1, + "assumedAmountIn": "1579660", + "assumedAmountOut": "2811" } ], "routeProcessorAddr": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", "tx": { "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", "to": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", - "data": "0x6678ec1f000000000000000000000000850a57630a2012b2494779fbc86bbc24f2a7baef00000000000000000000000000000000000000000000000000000000000000af000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000056bc75e2d631000000000000000000000000000001bfd67037b42cf73acf2047067bd4f2c47d9bfd600000000000000000000000000000000000000000000000000000000000112f1000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002470301ffff0201f2614A233c7C3e7f08b1F887Ba133a13f1eb2c550d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270010d500B1d8E8eF31E21C99d1Db9A6444d3ADf127004051f008531c4e29491fE6e5e87AF6054FC20FcCf0b429001f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55000bb81f590121988C9CFD08db3b5793c2C6782271dC9474925101f2614A233c7C3e7f08b1F887Ba133a13f1eb2c554a6b00c4e595acDD7d12feC385E5dA5D43160e8A0bAC0E01E62Ec2e799305E0D367b0Cc3ee2CdA135bF89816000bb8ffff01f1A12338D39Fc085D8631E1A745B5116BC9b2A3201E62Ec2e799305E0D367b0Cc3ee2CdA135bF89816012791Bca1f2de4661ED88A30C99A7a9449Aa84174042aad00D02b870c556480491c70AaF98C297fddd93F6f5C00f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55000bb8cccd01F88dE8Aaa065EcBF9a3C67f7A93b4c82595f6D6F00f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55800c01EF69494EeA0ecBFbbFa1cfd5386268a562bc875F01E62Ec2e799305E0D367b0Cc3ee2CdA135bF89816ffff014646E8A5e1d14E2DA01577822D6346c7883C689001f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55018f3Cf7ad23Cd3CaDbD9735AFf958023239c6A06301ffff01333923EC5bb34bf25468d77C641771e86Ee7bfCf00E62Ec2e799305E0D367b0Cc3ee2CdA135bF89816047ceB23fD6bC0adD59E62ac25578270cFf1b9f61900E62Ec2e799305E0D367b0Cc3ee2CdA135bF8981600f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55000bb800000000000000000000000000000000000000000000000000", + "data": "0x6678ec1f000000000000000000000000850a57630a2012b2494779fbc86bbc24f2a7baef00000000000000000000000000000000000000000000000000000000000000ae000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee0000000000000000000000000000000000000000000000056bc75e2d631000000000000000000000000000001bfd67037b42cf73acf2047067bd4f2c47d9bfd600000000000000000000000000000000000000000000000000000000000110f0000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001ec0301ffff0201f2614A233c7C3e7f08b1F887Ba133a13f1eb2c550d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270010d500B1d8E8eF31E21C99d1Db9A6444d3ADf127005051f008531c4e29491fE6e5e87AF6054FC20FcCf0b429001f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55000bb8029d01934F3F8749164111f0386eCE4f4965a687E576d501f2614A233c7C3e7f08b1F887Ba133a13f1eb2c5505470121988C9CFD08db3b5793c2C6782271dC9474925101f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55fd4d01f1A12338D39Fc085D8631E1A745B5116BC9b2A3201E62Ec2e799305E0D367b0Cc3ee2CdA135bF89816ffff007d88D931504D04BFBEE6F9745297A93063CAb24c013E9a0586088caEb2aDFf32B0C06CfA44151c7a5B000bb804D6DF932A45C0f255f85145f286eA0b292B21C90B003E9a0586088caEb2aDFf32B0C06CfA44151c7a5B00f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55000bb8047ceB23fD6bC0adD59E62ac25578270cFf1b9f61900E62Ec2e799305E0D367b0Cc3ee2CdA135bF8981600f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55000bb8012791Bca1f2de4661ED88A30C99A7a9449Aa8417401ffff01F88dE8Aaa065EcBF9a3C67f7A93b4c82595f6D6F00f2614A233c7C3e7f08b1F887Ba133a13f1eb2c550000000000000000000000000000000000000000", "value": "100000000000000000000" } } \ No newline at end of file diff --git a/apps/web/test/swap/mock/137-usdc-to-native.json b/apps/web/test/swap/mock/137-usdc-to-native.json index b289a3a97e..b9529b60db 100644 --- a/apps/web/test/swap/mock/137-usdc-to-native.json +++ b/apps/web/test/swap/mock/137-usdc-to-native.json @@ -7,6 +7,12 @@ "name": "USD Coin", "decimals": 6 }, + { + "address": "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", + "symbol": "WMATIC", + "name": "Wrapped Matic", + "decimals": 18 + }, { "address": "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", "symbol": "USDC", @@ -20,10 +26,10 @@ "decimals": 6 }, { - "address": "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", - "symbol": "WMATIC", - "name": "Wrapped Matic", - "decimals": 18 + "address": "0x1BFD67037B42Cf73acF2047067bd4F2C47D9BfD6", + "symbol": "WBTC", + "name": "(PoS) Wrapped BTC", + "decimals": 8 }, { "address": "0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063", @@ -32,9 +38,9 @@ "decimals": 18 }, { - "address": "0xD6DF932A45C0f255f85145f286eA0b292B21C90B", - "symbol": "AAVE", - "name": "Aave (PoS)", + "address": "0x45c32fA6DF82ead1e2EF74d17b76547EDdFaFF89", + "symbol": "FRAX", + "name": "Frax", "decimals": 18 }, { @@ -51,23 +57,34 @@ } ], "tokenFrom": 0, - "tokenTo": 7, - "swapPrice": 2454483305408.1904, - "priceImpact": -0.0012706043226990982, + "tokenTo": 8, + "swapPrice": 2530082355848.2344, + "priceImpact": 0.000979278072000711, "amountIn": "1000000", - "assumedAmountOut": "2454483305408190464", - "gasSpent": 1090000, + "assumedAmountOut": "2530082355848236032", + "gasSpent": 1450000, "route": [ + { + "poolAddress": "0x96c7FC08D8CDACdB95a8613b19fffe4D54307263", + "poolType": "Classic", + "poolName": "SushiSwapV2 0.3%", + "poolFee": 0.003, + "tokenFrom": 0, + "tokenTo": 1, + "share": 0.03, + "assumedAmountIn": "29999", + "assumedAmountOut": "76139156023664560" + }, { "poolAddress": "0x00604DCc4463D6c39D957BC25C7b6683dDD2Ba90", "poolType": "Concentrated", "poolName": "SushiSwapV3 0.01%", "poolFee": 0.0001, "tokenFrom": 0, - "tokenTo": 1, - "share": 0.3333333333333333, - "assumedAmountIn": "333333", - "assumedAmountOut": "333309" + "tokenTo": 2, + "share": 0.95, + "assumedAmountIn": "950004", + "assumedAmountOut": "949945" }, { "poolAddress": "0x498d5cdcC5667b21210b49442Bf2D8792527194d", @@ -75,115 +92,159 @@ "poolName": "SushiSwapV3 0.01%", "poolFee": 0.0001, "tokenFrom": 0, - "tokenTo": 2, - "share": 0.6666666666666666, - "assumedAmountIn": "666667", - "assumedAmountOut": "666254" + "tokenTo": 3, + "share": 0.02, + "assumedAmountIn": "19997", + "assumedAmountOut": "19988" }, { - "poolAddress": "0xdB0101bE2132408e65B30246aa662e4D6f49599c", + "poolAddress": "0x5212438DfBA63c6C4021AF24C96E6BAE7d6fba71", "poolType": "Concentrated", - "poolName": "SushiSwapV3 0.3%", - "poolFee": 0.003, + "poolName": "SushiSwapV3 0.01%", + "poolFee": 0.0001, + "tokenFrom": 3, + "tokenTo": 1, + "share": 1, + "assumedAmountIn": "19988", + "assumedAmountOut": "50730835238416672" + }, + { + "poolAddress": "0x21988C9CFD08db3b5793c2C6782271dC94749251", + "poolType": "Concentrated", + "poolName": "SushiSwapV3 0.05%", + "poolFee": 0.0005, "tokenFrom": 2, - "tokenTo": 3, - "share": 0.7499999999999997, - "assumedAmountIn": "499687", - "assumedAmountOut": "1224956348951011840" + "tokenTo": 1, + "share": 0.8736842093327086, + "assumedAmountIn": "829953", + "assumedAmountOut": "2099409626577039104" }, { - "poolAddress": "0x7e5Fc5677Dfb16dFBC250AFf8F90E6ceF743Ca01", + "poolAddress": "0x135A796632229424B10237f8f127898dbf6F793f", "poolType": "Concentrated", - "poolName": "SushiSwapV3 0.01%", - "poolFee": 0.0001, + "poolName": "SushiSwapV3 0.05%", + "poolFee": 0.0005, "tokenFrom": 2, "tokenTo": 4, - "share": 0.12499999466481652, - "assumedAmountIn": "83282", - "assumedAmountOut": "83240476591060048" + "share": 0.010526315954472305, + "assumedAmountIn": "9998", + "assumedAmountOut": "18" }, { - "poolAddress": "0xa543Ba3fd79a03788e5521a0Ce48B3F2Bf93b2c1", - "poolType": "Classic", - "poolName": "SushiSwapV2 0.3%", - "poolFee": 0.003, + "poolAddress": "0x4646E8A5e1d14E2DA01577822D6346c7883C6890", + "poolType": "Concentrated", + "poolName": "SushiSwapV3 0.01%", + "poolFee": 0.0001, "tokenFrom": 2, "tokenTo": 5, - "share": 0.12500000533518382, - "assumedAmountIn": "83285", - "assumedAmountOut": "822829204479297" + "share": 0.11578947471281899, + "assumedAmountIn": "109994", + "assumedAmountOut": "109981406034812832" }, { - "poolAddress": "0x7d88D931504D04BFBEE6F9745297A93063CAb24c", + "poolAddress": "0x8531c4e29491fE6e5e87AF6054FC20FcCf0b4290", "poolType": "Classic", "poolName": "SushiSwapV2 0.3%", "poolFee": 0.003, - "tokenFrom": 5, - "tokenTo": 3, - "share": 1, - "assumedAmountIn": "822829204479297", - "assumedAmountOut": "204645614090705952" + "tokenFrom": 4, + "tokenTo": 1, + "share": 0.8354280246266744, + "assumedAmountIn": "15", + "assumedAmountOut": "21160170833119080" }, { - "poolAddress": "0xe58517662569c742388b90dC5461F7DBBBD8aE58", - "poolType": "Concentrated", - "poolName": "SushiSwapV3 0.3%", + "poolAddress": "0x7a1d5E67c3a273274766E241363E3E98e721E456", + "poolType": "Classic", + "poolName": "SushiSwapV2 0.3%", "poolFee": 0.003, "tokenFrom": 4, - "tokenTo": 3, - "share": 1, - "assumedAmountIn": "83240476591060048", - "assumedAmountOut": "204624511482240192" + "tokenTo": 5, + "share": 0.16457197537332557, + "assumedAmountIn": "3", + "assumedAmountOut": "1701942943600490" }, { - "poolAddress": "0x934F3F8749164111f0386eCE4f4965a687E576d5", - "poolType": "Concentrated", - "poolName": "SushiSwapV3 0.01%", - "poolFee": 0.0001, - "tokenFrom": 1, - "tokenTo": 3, - "share": 0.24999999895779174, - "assumedAmountIn": "83328", - "assumedAmountOut": "204592268592704096" + "poolAddress": "0x16d4618717B0A3C7D7Cc261110e61A02E7FB0b73", + "poolType": "Classic", + "poolName": "SushiSwapV2 0.3%", + "poolFee": 0.003, + "tokenFrom": 5, + "tokenTo": 6, + "share": 0.08494474705336469, + "assumedAmountIn": "9487162642295370", + "assumedAmountOut": "9641366168050864" }, { - "poolAddress": "0xEF69494EeA0ecBFbbFa1cfd5386268a562bc875F", + "poolAddress": "0x333923EC5bb34bf25468d77C641771e86Ee7bfCf", "poolType": "Concentrated", "poolName": "SushiSwapV3 0.01%", "poolFee": 0.0001, - "tokenFrom": 1, - "tokenTo": 6, - "share": 0.7500000010422082, - "assumedAmountIn": "249981", - "assumedAmountOut": "101344067904539" + "tokenFrom": 5, + "tokenTo": 7, + "share": 0.9150552529466353, + "assumedAmountIn": "102196186336117952", + "assumedAmountOut": "42656905353976" }, { "poolAddress": "0xf1A12338D39Fc085D8631E1A745B5116BC9b2A32", "poolType": "Concentrated", "poolName": "SushiSwapV3 0.05%", "poolFee": 0.0005, + "tokenFrom": 7, + "tokenTo": 1, + "share": 0.3333135183356411, + "assumedAmountIn": "14218317548672", + "assumedAmountOut": "86160838774417536" + }, + { + "poolAddress": "0x89A54409f8ce05b91317C0e2a985E8d30de93341", + "poolType": "Concentrated", + "poolName": "SushiSwapV3 0.3%", + "poolFee": 0.003, + "tokenFrom": 7, + "tokenTo": 1, + "share": 0.5000182900938339, + "assumedAmountIn": "21329266312753", + "assumedAmountOut": "129318380207947136" + }, + { + "poolAddress": "0x0287Ef25D7bD3fFEc6a3A31F9496C797ACd78225", + "poolType": "Concentrated", + "poolName": "SushiSwapV3 1%", + "poolFee": 0.01, + "tokenFrom": 7, + "tokenTo": 1, + "share": 0.16666819157052493, + "assumedAmountIn": "7109321492551", + "assumedAmountOut": "43098463620553504" + }, + { + "poolAddress": "0xE7C714DD3dD70eE04EB69A856655765454E77c88", + "poolType": "Classic", + "poolName": "SushiSwapV2 0.3%", + "poolFee": 0.003, "tokenFrom": 6, - "tokenTo": 3, + "tokenTo": 1, "share": 1, - "assumedAmountIn": "101344067904539", - "assumedAmountOut": "615664562291528320" + "assumedAmountIn": "9641366168050864", + "assumedAmountOut": "24064884573077836" }, { "poolAddress": "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", "poolType": "Bridge", "poolName": "Wrap", "poolFee": 0, - "tokenFrom": 3, - "tokenTo": 7, + "tokenFrom": 1, + "tokenTo": 8, "share": 1, - "assumedAmountIn": "2454483305408190464", - "assumedAmountOut": "2454483305408190464" + "assumedAmountIn": "2530082355848236032", + "assumedAmountOut": "2530082355848236032" } ], "routeProcessorAddr": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", "tx": { "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", "to": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", - "data": "0x2646478b0000000000000000000000003c499c542cef5e3811e1192ce70d8cc03d5c335900000000000000000000000000000000000000000000000000000000000f4240000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee00000000000000000000000000000000000000000000000021e479dd325a1647000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000026d023c499c542cEF5E3811e1192ce70d8cC03d5c33590255550100604DCc4463D6c39D957BC25C7b6683dDD2Ba9000f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55ffff01498d5cdcC5667b21210b49442Bf2D8792527194d01f2614A233c7C3e7f08b1F887Ba133a13f1eb2c5501c2132D05D31c914a87C6611C10748AEb04B58e8F03bfff01dB0101bE2132408e65B30246aa662e4D6f49599c00f2614A233c7C3e7f08b1F887Ba133a13f1eb2c557fff017e5Fc5677Dfb16dFBC250AFf8F90E6ceF743Ca0100f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55ffff00a543Ba3fd79a03788e5521a0Ce48B3F2Bf93b2c1017d88D931504D04BFBEE6F9745297A93063CAb24c000bb804D6DF932A45C0f255f85145f286eA0b292B21C90B007d88D931504D04BFBEE6F9745297A93063CAb24c00f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55000bb8018f3Cf7ad23Cd3CaDbD9735AFf958023239c6A06301ffff01e58517662569c742388b90dC5461F7DBBBD8aE5800f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55012791Bca1f2de4661ED88A30C99A7a9449Aa8417402400001934F3F8749164111f0386eCE4f4965a687E576d500f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55ffff01EF69494EeA0ecBFbbFa1cfd5386268a562bc875F01f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55017ceB23fD6bC0adD59E62ac25578270cFf1b9f61901ffff01f1A12338D39Fc085D8631E1A745B5116BC9b2A3200f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55010d500B1d8E8eF31E21C99d1Db9A6444d3ADf127001ffff0200f39Fd6e51aad88F6F4ce6aB8827279cffFb9226600000000000000000000000000000000000000" + "data": "0x2646478b0000000000000000000000003c499c542cef5e3811e1192ce70d8cc03d5c335900000000000000000000000000000000000000000000000000000000000f4240000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee00000000000000000000000000000000000000000000000022efb703e4741723000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000368023c499c542cEF5E3811e1192ce70d8cC03d5c33590307ae0096c7FC08D8CDACdB95a8613b19fffe4D5430726300f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55000bb8fab80100604DCc4463D6c39D957BC25C7b6683dDD2Ba9000f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55ffff01498d5cdcC5667b21210b49442Bf2D8792527194d01f2614A233c7C3e7f08b1F887Ba133a13f1eb2c5501c2132D05D31c914a87C6611C10748AEb04B58e8F01ffff015212438DfBA63c6C4021AF24C96E6BAE7d6fba7100f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55012791Bca1f2de4661ED88A30C99A7a9449Aa8417403dfa90121988C9CFD08db3b5793c2C6782271dC9474925100f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55155501135A796632229424B10237f8f127898dbf6F793f00f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55ffff014646E8A5e1d14E2DA01577822D6346c7883C689001f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55011BFD67037B42Cf73acF2047067bd4F2C47D9BfD602d5de008531c4e29491fE6e5e87AF6054FC20FcCf0b429000f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55000bb8ffff007a1d5E67c3a273274766E241363E3E98e721E45601f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55000bb8018f3Cf7ad23Cd3CaDbD9735AFf958023239c6A0630215bf0016d4618717B0A3C7D7Cc261110e61A02E7FB0b7300E7C714DD3dD70eE04EB69A856655765454E77c88000bb8ffff01333923EC5bb34bf25468d77C641771e86Ee7bfCf00f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55017ceB23fD6bC0adD59E62ac25578270cFf1b9f61903555401f1A12338D39Fc085D8631E1A745B5116BC9b2A3200f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55c0000189A54409f8ce05b91317C0e2a985E8d30de9334100f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55ffff010287Ef25D7bD3fFEc6a3A31F9496C797ACd7822500f2614A233c7C3e7f08b1F887Ba133a13f1eb2c550445c32fA6DF82ead1e2EF74d17b76547EDdFaFF8900E7C714DD3dD70eE04EB69A856655765454E77c8800f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55000bb8010d500B1d8E8eF31E21C99d1Db9A6444d3ADf127001ffff0200f39Fd6e51aad88F6F4ce6aB8827279cffFb92266000000000000000000000000000000000000000000000000" } } \ No newline at end of file diff --git a/apps/web/test/swap/mock/137-usdc-to-usdt.json b/apps/web/test/swap/mock/137-usdc-to-usdt.json index d167803b68..1ef86dfa48 100644 --- a/apps/web/test/swap/mock/137-usdc-to-usdt.json +++ b/apps/web/test/swap/mock/137-usdc-to-usdt.json @@ -16,10 +16,10 @@ ], "tokenFrom": 0, "tokenTo": 1, - "swapPrice": 0.9993819999999993, - "priceImpact": 0.0017230930770902875, + "swapPrice": 0.999587, + "priceImpact": -0.0009349440797652431, "amountIn": "1000000", - "assumedAmountOut": "999382", + "assumedAmountOut": "999587", "gasSpent": 110000, "route": [ { @@ -31,13 +31,13 @@ "tokenTo": 1, "share": 1, "assumedAmountIn": "1000000", - "assumedAmountOut": "999382" + "assumedAmountOut": "999587" } ], "routeProcessorAddr": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", "tx": { "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", "to": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", - "data": "0x2646478b0000000000000000000000003c499c542cef5e3811e1192ce70d8cc03d5c335900000000000000000000000000000000000000000000000000000000000f4240000000000000000000000000c2132d05d31c914a87c6611c10748aeb04b58e8f00000000000000000000000000000000000000000000000000000000000f2c51000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000042023c499c542cEF5E3811e1192ce70d8cC03d5c335901ffff01498d5cdcC5667b21210b49442Bf2D8792527194d01f39Fd6e51aad88F6F4ce6aB8827279cffFb92266000000000000000000000000000000000000000000000000000000000000" + "data": "0x2646478b0000000000000000000000003c499c542cef5e3811e1192ce70d8cc03d5c335900000000000000000000000000000000000000000000000000000000000f4240000000000000000000000000c2132d05d31c914a87c6611c10748aeb04b58e8f00000000000000000000000000000000000000000000000000000000000f2d1d000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000042023c499c542cEF5E3811e1192ce70d8cC03d5c335901ffff01498d5cdcC5667b21210b49442Bf2D8792527194d01f39Fd6e51aad88F6F4ce6aB8827279cffFb92266000000000000000000000000000000000000000000000000000000000000" } } \ No newline at end of file diff --git a/apps/web/test/swap/mock/137-usdt-to-native.json b/apps/web/test/swap/mock/137-usdt-to-native.json index e67945443d..b213e486af 100644 --- a/apps/web/test/swap/mock/137-usdt-to-native.json +++ b/apps/web/test/swap/mock/137-usdt-to-native.json @@ -13,6 +13,12 @@ "name": "Wrapped Matic", "decimals": 18 }, + { + "address": "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", + "symbol": "USDC", + "name": "USD Coin (PoS)", + "decimals": 6 + }, { "address": "0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359", "symbol": "USDC", @@ -26,16 +32,16 @@ "decimals": 18 }, { - "address": "0xD6DF932A45C0f255f85145f286eA0b292B21C90B", - "symbol": "AAVE", - "name": "Aave (PoS)", - "decimals": 18 + "address": "0x1BFD67037B42Cf73acF2047067bd4F2C47D9BfD6", + "symbol": "WBTC", + "name": "(PoS) Wrapped BTC", + "decimals": 8 }, { - "address": "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", - "symbol": "USDC", - "name": "USD Coin (PoS)", - "decimals": 6 + "address": "0x45c32fA6DF82ead1e2EF74d17b76547EDdFaFF89", + "symbol": "FRAX", + "name": "Frax", + "decimals": 18 }, { "address": "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619", @@ -51,111 +57,188 @@ } ], "tokenFrom": 0, - "tokenTo": 7, - "swapPrice": 2455069920207.021, - "priceImpact": -0.0026185772674121033, + "tokenTo": 8, + "swapPrice": 2530663331324.462, + "priceImpact": 0.0020955509980018494, "amountIn": "1000000", - "assumedAmountOut": "2455069920207021056", - "gasSpent": 980000, + "assumedAmountOut": "2530663331324464128", + "gasSpent": 1600000, "route": [ { - "poolAddress": "0xdB0101bE2132408e65B30246aa662e4D6f49599c", + "poolAddress": "0x5212438DfBA63c6C4021AF24C96E6BAE7d6fba71", "poolType": "Concentrated", - "poolName": "SushiSwapV3 0.3%", - "poolFee": 0.003, + "poolName": "SushiSwapV3 0.01%", + "poolFee": 0.0001, "tokenFrom": 0, "tokenTo": 1, - "share": 0.5833333333333333, - "assumedAmountIn": "583337", - "assumedAmountOut": "1429646812130815488" + "share": 0.02, + "assumedAmountIn": "20004", + "assumedAmountOut": "50768754238099456" }, { - "poolAddress": "0x498d5cdcC5667b21210b49442Bf2D8792527194d", + "poolAddress": "0x8CFaab34f5159abf9C35587AC40d09a05dC94765", "poolType": "Concentrated", "poolName": "SushiSwapV3 0.01%", "poolFee": 0.0001, "tokenFrom": 0, "tokenTo": 2, - "share": 0.25, - "assumedAmountIn": "249997", - "assumedAmountOut": "250101" + "share": 0.94, + "assumedAmountIn": "939994", + "assumedAmountOut": "940157" }, { - "poolAddress": "0x7e5Fc5677Dfb16dFBC250AFf8F90E6ceF743Ca01", + "poolAddress": "0x498d5cdcC5667b21210b49442Bf2D8792527194d", "poolType": "Concentrated", "poolName": "SushiSwapV3 0.01%", "poolFee": 0.0001, "tokenFrom": 0, "tokenTo": 3, - "share": 0.08333333333333333, - "assumedAmountIn": "83331", - "assumedAmountOut": "83289426837355936" + "share": 0.03, + "assumedAmountIn": "30001", + "assumedAmountOut": "30006" }, { - "poolAddress": "0xa543Ba3fd79a03788e5521a0Ce48B3F2Bf93b2c1", - "poolType": "Classic", - "poolName": "SushiSwapV2 0.3%", - "poolFee": 0.003, + "poolAddress": "0x7e5Fc5677Dfb16dFBC250AFf8F90E6ceF743Ca01", + "poolType": "Concentrated", + "poolName": "SushiSwapV3 0.01%", + "poolFee": 0.0001, "tokenFrom": 0, "tokenTo": 4, - "share": 0.08333333333333333, - "assumedAmountIn": "83335", - "assumedAmountOut": "823321492277830" + "share": 0.01, + "assumedAmountIn": "10001", + "assumedAmountOut": "10000610985504388" }, { - "poolAddress": "0x7d88D931504D04BFBEE6F9745297A93063CAb24c", + "poolAddress": "0x96c7FC08D8CDACdB95a8613b19fffe4D54307263", "poolType": "Classic", "poolName": "SushiSwapV2 0.3%", "poolFee": 0.003, - "tokenFrom": 4, + "tokenFrom": 3, "tokenTo": 1, "share": 1, - "assumedAmountIn": "823321492277830", - "assumedAmountOut": "204768029241574560" + "assumedAmountIn": "30006", + "assumedAmountOut": "76156857317254224" }, { - "poolAddress": "0xe58517662569c742388b90dC5461F7DBBBD8aE58", + "poolAddress": "0x21988C9CFD08db3b5793c2C6782271dC94749251", "poolType": "Concentrated", - "poolName": "SushiSwapV3 0.3%", - "poolFee": 0.003, - "tokenFrom": 3, + "poolName": "SushiSwapV3 0.05%", + "poolFee": 0.0005, + "tokenFrom": 2, "tokenTo": 1, - "share": 1, - "assumedAmountIn": "83289426837355936", - "assumedAmountOut": "204744622631952640" + "share": 0.8829787208693706, + "assumedAmountIn": "830138", + "assumedAmountOut": "2099875136807535360" }, { - "poolAddress": "0x00604DCc4463D6c39D957BC25C7b6683dDD2Ba90", + "poolAddress": "0x135A796632229424B10237f8f127898dbf6F793f", "poolType": "Concentrated", - "poolName": "SushiSwapV3 0.01%", - "poolFee": 0.0001, + "poolName": "SushiSwapV3 0.05%", + "poolFee": 0.0005, "tokenFrom": 2, "tokenTo": 5, - "share": 1, - "assumedAmountIn": "250101", - "assumedAmountOut": "250082" + "share": 0.010638298267221975, + "assumedAmountIn": "10002", + "assumedAmountOut": "18" }, { - "poolAddress": "0xEF69494EeA0ecBFbbFa1cfd5386268a562bc875F", + "poolAddress": "0x4646E8A5e1d14E2DA01577822D6346c7883C6890", "poolType": "Concentrated", "poolName": "SushiSwapV3 0.01%", "poolFee": 0.0001, + "tokenFrom": 2, + "tokenTo": 4, + "share": 0.1063829808634075, + "assumedAmountIn": "100017", + "assumedAmountOut": "100004550643819744" + }, + { + "poolAddress": "0x8531c4e29491fE6e5e87AF6054FC20FcCf0b4290", + "poolType": "Classic", + "poolName": "SushiSwapV2 0.3%", + "poolFee": 0.003, + "tokenFrom": 5, + "tokenTo": 1, + "share": 0.8354290495669457, + "assumedAmountIn": "15", + "assumedAmountOut": "21160170833119080" + }, + { + "poolAddress": "0x7a1d5E67c3a273274766E241363E3E98e721E456", + "poolType": "Classic", + "poolName": "SushiSwapV2 0.3%", + "poolFee": 0.003, "tokenFrom": 5, + "tokenTo": 4, + "share": 0.16457095043305434, + "assumedAmountIn": "3", + "assumedAmountOut": "1701942943600490" + }, + { + "poolAddress": "0x16d4618717B0A3C7D7Cc261110e61A02E7FB0b73", + "poolType": "Classic", + "poolName": "SushiSwapV2 0.3%", + "poolFee": 0.003, + "tokenFrom": 4, "tokenTo": 6, - "share": 1, - "assumedAmountIn": "250082", - "assumedAmountOut": "101384544390673" + "share": 0.08494387635821668, + "assumedAmountIn": "9489180608186028", + "assumedAmountOut": "9643406528547926" + }, + { + "poolAddress": "0x333923EC5bb34bf25468d77C641771e86Ee7bfCf", + "poolType": "Concentrated", + "poolName": "SushiSwapV3 0.01%", + "poolFee": 0.0001, + "tokenFrom": 4, + "tokenTo": 7, + "share": 0.9150561236417833, + "assumedAmountIn": "102217923964738592", + "assumedAmountOut": "42665977414274" }, { "poolAddress": "0xf1A12338D39Fc085D8631E1A745B5116BC9b2A32", "poolType": "Concentrated", "poolName": "SushiSwapV3 0.05%", "poolFee": 0.0005, + "tokenFrom": 7, + "tokenTo": 1, + "share": 0.333313505190406, + "assumedAmountIn": "14221341430341", + "assumedAmountOut": "86179163031731344" + }, + { + "poolAddress": "0x89A54409f8ce05b91317C0e2a985E8d30de93341", + "poolType": "Concentrated", + "poolName": "SushiSwapV3 0.3%", + "poolFee": 0.003, + "tokenFrom": 7, + "tokenTo": 1, + "share": 0.5000183008160737, + "assumedAmountIn": "21333802515942", + "assumedAmountOut": "129345674506791952" + }, + { + "poolAddress": "0x0287Ef25D7bD3fFEc6a3A31F9496C797ACd78225", + "poolType": "Concentrated", + "poolName": "SushiSwapV3 1%", + "poolFee": 0.01, + "tokenFrom": 7, + "tokenTo": 1, + "share": 0.16666819399352029, + "assumedAmountIn": "7110833467991", + "assumedAmountOut": "43107599533427120" + }, + { + "poolAddress": "0xE7C714DD3dD70eE04EB69A856655765454E77c88", + "poolType": "Classic", + "poolName": "SushiSwapV2 0.3%", + "poolFee": 0.003, "tokenFrom": 6, "tokenTo": 1, "share": 1, - "assumedAmountIn": "101384544390673", - "assumedAmountOut": "615910456202678272" + "assumedAmountIn": "9643406528547926", + "assumedAmountOut": "24069975056505488" }, { "poolAddress": "0x0d500B1d8E8eF31E21C99d1Db9A6444d3ADf1270", @@ -163,16 +246,16 @@ "poolName": "Wrap", "poolFee": 0, "tokenFrom": 1, - "tokenTo": 7, + "tokenTo": 8, "share": 1, - "assumedAmountIn": "2455069920207021056", - "assumedAmountOut": "2455069920207021056" + "assumedAmountIn": "2530663331324463616", + "assumedAmountOut": "2530663331324463616" } ], "routeProcessorAddr": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", "tx": { "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", "to": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", - "data": "0x2646478b000000000000000000000000c2132d05d31c914a87c6611c10748aeb04b58e8f00000000000000000000000000000000000000000000000000000000000f4240000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee00000000000000000000000000000000000000000000000021e68cb83039009e000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000024102c2132D05D31c914a87C6611C10748AEb04B58e8F04955501dB0101bE2132408e65B30246aa662e4D6f49599c00f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55999901498d5cdcC5667b21210b49442Bf2D8792527194d00f2614A233c7C3e7f08b1F887Ba133a13f1eb2c557fff017e5Fc5677Dfb16dFBC250AFf8F90E6ceF743Ca0100f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55ffff00a543Ba3fd79a03788e5521a0Ce48B3F2Bf93b2c1017d88D931504D04BFBEE6F9745297A93063CAb24c000bb804D6DF932A45C0f255f85145f286eA0b292B21C90B007d88D931504D04BFBEE6F9745297A93063CAb24c00f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55000bb8018f3Cf7ad23Cd3CaDbD9735AFf958023239c6A06301ffff01e58517662569c742388b90dC5461F7DBBBD8aE5800f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55013c499c542cEF5E3811e1192ce70d8cC03d5c335901ffff0100604DCc4463D6c39D957BC25C7b6683dDD2Ba9000f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55012791Bca1f2de4661ED88A30C99A7a9449Aa8417401ffff01EF69494EeA0ecBFbbFa1cfd5386268a562bc875F01f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55017ceB23fD6bC0adD59E62ac25578270cFf1b9f61901ffff01f1A12338D39Fc085D8631E1A745B5116BC9b2A3200f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55010d500B1d8E8eF31E21C99d1Db9A6444d3ADf127001ffff0200f39Fd6e51aad88F6F4ce6aB8827279cffFb9226600000000000000000000000000000000000000000000000000000000000000" + "data": "0x2646478b000000000000000000000000c2132d05d31c914a87c6611c10748aeb04b58e8f00000000000000000000000000000000000000000000000000000000000f4240000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee00000000000000000000000000000000000000000000000022f1c4c47127210f000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb9226600000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000039102c2132D05D31c914a87C6611C10748AEb04B58e8F04051f015212438DfBA63c6C4021AF24C96E6BAE7d6fba7100f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55f58c018CFaab34f5159abf9C35587AC40d09a05dC9476500f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55bfff01498d5cdcC5667b21210b49442Bf2D8792527194d0096c7FC08D8CDACdB95a8613b19fffe4D54307263ffff017e5Fc5677Dfb16dFBC250AFf8F90E6ceF743Ca0100f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55043c499c542cEF5E3811e1192ce70d8cC03d5c33590096c7FC08D8CDACdB95a8613b19fffe4D5430726300f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55000bb8012791Bca1f2de4661ED88A30C99A7a9449Aa8417403e20a0121988C9CFD08db3b5793c2C6782271dC9474925100f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55174601135A796632229424B10237f8f127898dbf6F793f00f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55ffff014646E8A5e1d14E2DA01577822D6346c7883C689001f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55011BFD67037B42Cf73acF2047067bd4F2C47D9BfD602d5de008531c4e29491fE6e5e87AF6054FC20FcCf0b429000f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55000bb8ffff007a1d5E67c3a273274766E241363E3E98e721E45601f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55000bb8018f3Cf7ad23Cd3CaDbD9735AFf958023239c6A0630215bf0016d4618717B0A3C7D7Cc261110e61A02E7FB0b7300E7C714DD3dD70eE04EB69A856655765454E77c88000bb8ffff01333923EC5bb34bf25468d77C641771e86Ee7bfCf00f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55017ceB23fD6bC0adD59E62ac25578270cFf1b9f61903555401f1A12338D39Fc085D8631E1A745B5116BC9b2A3200f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55c0000189A54409f8ce05b91317C0e2a985E8d30de9334100f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55ffff010287Ef25D7bD3fFEc6a3A31F9496C797ACd7822500f2614A233c7C3e7f08b1F887Ba133a13f1eb2c550445c32fA6DF82ead1e2EF74d17b76547EDdFaFF8900E7C714DD3dD70eE04EB69A856655765454E77c8800f2614A233c7C3e7f08b1F887Ba133a13f1eb2c55000bb8010d500B1d8E8eF31E21C99d1Db9A6444d3ADf127001ffff0200f39Fd6e51aad88F6F4ce6aB8827279cffFb92266000000000000000000000000000000" } } \ No newline at end of file diff --git a/apps/web/test/swap/simple.test.ts b/apps/web/test/swap/simple.test.ts index 033be0172c..bf36690828 100644 --- a/apps/web/test/swap/simple.test.ts +++ b/apps/web/test/swap/simple.test.ts @@ -81,7 +81,7 @@ test.beforeEach(async ({ page, next }) => { }) test('Wrap and unwrap', async ({ page }) => { - test.slow() + // test.slow() const swapPage = new SwapPage(page, chainId) await swapPage.goTo(url) await swapPage.connect() @@ -94,7 +94,7 @@ test('Wrap and unwrap', async ({ page }) => { }) test('swap Native to USDC, then USDC to NATIVE', async ({ page }) => { - test.slow() + // test.slow() const swapPage = new SwapPage(page, chainId) await swapPage.goTo(url) await swapPage.connect() @@ -107,7 +107,7 @@ test('swap Native to USDC, then USDC to NATIVE', async ({ page }) => { }) test('swap Native to USDT, then USDT to NATIVE', async ({ page }) => { - test.slow() + // test.slow() const swapPage = new SwapPage(page, chainId) await swapPage.goTo(url) await swapPage.connect() @@ -122,7 +122,7 @@ test('swap Native to USDT, then USDT to NATIVE', async ({ page }) => { test('Swap Native to USDC, USDC to USDT then USDT to NATIVE', async ({ page, }) => { - test.slow() + // test.slow() const swapPage = new SwapPage(page, chainId) await swapPage.goTo(url) await swapPage.connect() @@ -138,7 +138,7 @@ test('Swap Native to USDC, USDC to USDT then USDT to NATIVE', async ({ }) test('Swap Native to WBTC', async ({ page }) => { - test.slow() + // test.slow() const swapPage = new SwapPage(page, chainId) await swapPage.goTo(url) await swapPage.connect() diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index dec2700e7e..60a91cefb1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -34,7 +34,7 @@ importers: version: 29.5.5 '@types/node': specifier: '20' - version: 20.10.0 + version: 20.14.14 dotenv-cli: specifier: 6.0.0 version: 6.0.0 @@ -46,13 +46,13 @@ importers: version: 2.0.5(eslint@8.43.0) jest: specifier: 29.7.0 - version: 29.7.0(@types/node@20.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)) + version: 29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4)) sort-package-json: specifier: 2.6.0 version: 2.6.0 ts-jest: specifier: 29.1.1 - version: 29.1.1(@babel/core@7.24.4)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.4))(jest@29.7.0(@types/node@20.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)))(typescript@5.4.5) + version: 29.1.1(@babel/core@7.24.4)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.4))(jest@29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4)))(typescript@5.5.4) turbo: specifier: 2.0.5 version: 2.0.5 @@ -104,13 +104,13 @@ importers: version: 4.17.17 '@types/node': specifier: '20' - version: 20.10.0 + version: 20.14.14 autocannon: specifier: 7.14.0 version: 7.14.0 ts-node: specifier: 10.9.2 - version: 10.9.2(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5) + version: 10.9.2(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5) typescript: specifier: 5.4.5 version: 5.4.5 @@ -162,16 +162,16 @@ importers: version: 4.17.17 '@types/node': specifier: '20' - version: 20.10.0 + version: 20.14.14 artillery: specifier: 2.0.5 - version: 2.0.5(@swc/core@1.4.2)(@types/node@20.10.0)(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10) + version: 2.0.5(@swc/core@1.4.2)(@types/node@20.14.14)(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10) autocannon: specifier: 7.14.0 version: 7.14.0 ts-node: specifier: 10.9.2 - version: 10.9.2(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5) + version: 10.9.2(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5) typescript: specifier: 5.4.5 version: 5.4.5 @@ -254,7 +254,7 @@ importers: version: 2.0.2 '@types/node': specifier: '20' - version: 20.10.0 + version: 20.14.14 typescript: specifier: 5.4.5 version: 5.4.5 @@ -315,7 +315,7 @@ importers: version: 1.3.7(@types/react-dom@18.2.6)(@types/react@18.2.14)(less@4.2.0)(postcss@8.4.23)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.4.5)(webpack@5.91.0(esbuild@0.18.20)) '@storybook/builder-vite': specifier: 7.4.6 - version: 7.4.6(typescript@5.4.5)(vite@4.3.9(@types/node@20.12.7)(less@4.2.0)(terser@5.30.3)) + version: 7.4.6(typescript@5.4.5)(vite@4.3.9(@types/node@22.1.0)(less@4.2.0)(terser@5.30.3)) '@storybook/cli': specifier: 7.4.6 version: 7.4.6(bufferutil@4.0.8)(utf-8-validate@5.0.10) @@ -324,7 +324,7 @@ importers: version: 7.4.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.4.5) '@storybook/react-vite': specifier: 7.4.6 - version: 7.4.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(rollup@3.29.4)(typescript@5.4.5)(vite@4.3.9(@types/node@20.12.7)(less@4.2.0)(terser@5.30.3)) + version: 7.4.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(rollup@3.29.4)(typescript@5.4.5)(vite@4.3.9(@types/node@22.1.0)(less@4.2.0)(terser@5.30.3)) '@sushiswap/typescript-config': specifier: workspace:* version: link:../../config/typescript @@ -333,7 +333,7 @@ importers: version: 18.2.14 '@vitejs/plugin-react': specifier: 4.1.0 - version: 4.1.0(vite@4.3.9(@types/node@20.12.7)(less@4.2.0)(terser@5.30.3)) + version: 4.1.0(vite@4.3.9(@types/node@22.1.0)(less@4.2.0)(terser@5.30.3)) autoprefixer: specifier: 10.4.14 version: 10.4.14(postcss@8.4.23) @@ -351,13 +351,13 @@ importers: version: 7.4.6(bufferutil@4.0.8)(utf-8-validate@5.0.10) tailwindcss: specifier: 3.3.2 - version: 3.3.2(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5)) + version: 3.3.2(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5)) typescript: specifier: 5.4.5 version: 5.4.5 vite: specifier: 4.3.9 - version: 4.3.9(@types/node@20.12.7)(less@4.2.0)(terser@5.30.3) + version: 4.3.9(@types/node@22.1.0)(less@4.2.0)(terser@5.30.3) apps/tron: dependencies: @@ -454,7 +454,7 @@ importers: version: 4.1.9 '@types/node': specifier: '20' - version: 20.10.0 + version: 20.14.14 '@types/react': specifier: 18.2.14 version: 18.2.14 @@ -481,7 +481,7 @@ importers: version: 8.4.23 tailwindcss: specifier: 3.3.2 - version: 3.3.2(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)) + version: 3.3.2(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5)) typescript: specifier: 5.4.5 version: 5.4.5 @@ -502,10 +502,10 @@ importers: version: 2.3.1(@aptos-labs/ts-sdk@1.14.0)(aptos@1.21.0)(react@18.2.0) '@aptstats/aptos-wallet-framework': specifier: ^0.0.6 - version: 0.0.6(@babel/plugin-syntax-flow@7.24.1(@babel/core@7.24.4))(@babel/plugin-transform-react-jsx@7.23.4(@babel/core@7.24.4))(@types/babel__core@7.20.5)(aptos@1.21.0)(bufferutil@4.0.8)(eslint@8.57.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))(type-fest@4.18.3)(typescript@5.4.5)(utf-8-validate@5.0.10)(vue-template-compiler@2.7.16) + version: 0.0.6(@babel/plugin-syntax-flow@7.24.1(@babel/core@7.24.4))(@babel/plugin-transform-react-jsx@7.23.4(@babel/core@7.24.4))(@types/babel__core@7.20.5)(aptos@1.21.0)(bufferutil@4.0.8)(eslint@8.57.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5))(type-fest@4.18.3)(typescript@5.4.5)(utf-8-validate@5.0.10)(vue-template-compiler@2.7.16) '@aptstats/safepal-wallet-extension': specifier: ^0.0.3 - version: 0.0.3(@babel/plugin-syntax-flow@7.24.1(@babel/core@7.24.4))(@babel/plugin-transform-react-jsx@7.23.4(@babel/core@7.24.4))(@types/babel__core@7.20.5)(aptos@1.21.0)(bufferutil@4.0.8)(eslint@8.57.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))(type-fest@4.18.3)(typescript@5.4.5)(utf-8-validate@5.0.10)(vue-template-compiler@2.7.16) + version: 0.0.3(@babel/plugin-syntax-flow@7.24.1(@babel/core@7.24.4))(@babel/plugin-transform-react-jsx@7.23.4(@babel/core@7.24.4))(@types/babel__core@7.20.5)(aptos@1.21.0)(bufferutil@4.0.8)(eslint@8.57.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5))(type-fest@4.18.3)(typescript@5.4.5)(utf-8-validate@5.0.10)(vue-template-compiler@2.7.16) '@blocto/aptos-wallet-adapter-plugin': specifier: ^0.2.9 version: 0.2.9(bufferutil@4.0.8)(utf-8-validate@5.0.10) @@ -790,8 +790,8 @@ importers: specifier: 4.2.9 version: 4.2.9 '@types/node': - specifier: '20' - version: 20.12.7 + specifier: '22' + version: 22.1.0 '@types/react': specifier: 18.2.14 version: 18.2.14 @@ -811,8 +811,8 @@ importers: specifier: 1.3.12 version: 1.3.12 '@viem/anvil': - specifier: 0.0.7 - version: 0.0.7(bufferutil@4.0.8)(utf-8-validate@5.0.10) + specifier: 0.0.10 + version: 0.0.10(bufferutil@4.0.8)(utf-8-validate@5.0.10) autoprefixer: specifier: 10.4.14 version: 10.4.14(postcss@8.4.23) @@ -830,7 +830,7 @@ importers: version: 1.1.2(typescript@5.4.5) tailwindcss: specifier: 3.3.2 - version: 3.3.2(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5)) + version: 3.3.2(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5)) tsx: specifier: ^4.16.5 version: 4.16.5 @@ -845,7 +845,7 @@ importers: dependencies: '@vercel/style-guide': specifier: 5.0.1 - version: 5.0.1(eslint@8.57.0)(jest@29.7.0(@types/node@20.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)))(typescript@5.4.5) + version: 5.0.1(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4)))(typescript@5.4.5) eslint-config-turbo: specifier: 2.0.5 version: 2.0.5(eslint@8.57.0) @@ -864,7 +864,7 @@ importers: version: 8.44.4 '@types/node': specifier: '20' - version: 20.10.0 + version: 20.14.14 typescript: specifier: 5.4.5 version: 5.4.5 @@ -873,28 +873,28 @@ importers: dependencies: '@matterlabs/hardhat-zksync-deploy': specifier: 0.6.2 - version: 0.6.2(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))(zksync-web3@0.13.4(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))) + version: 0.6.2(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10))(zksync-web3@0.13.4(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))) '@matterlabs/hardhat-zksync-solc': specifier: 0.3.14 - version: 0.3.14(encoding@0.1.13)(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + version: 0.3.14(encoding@0.1.13)(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10)) '@nomiclabs/hardhat-ethers': specifier: npm:hardhat-deploy-ethers@^0.3.0-beta.13 - version: hardhat-deploy-ethers@0.3.0-beta.13(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + version: hardhat-deploy-ethers@0.3.0-beta.13(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10)) '@nomiclabs/hardhat-etherscan': specifier: 3.1.3 - version: 3.1.3(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + version: 3.1.3(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10)) '@nomiclabs/hardhat-solhint': specifier: 2.0.1 - version: 2.0.1(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + version: 2.0.1(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10)) '@nomiclabs/hardhat-waffle': specifier: 2.0.3 - version: 2.0.3(ethereum-waffle@3.4.4(bufferutil@4.0.8)(encoding@0.1.13)(typescript@5.4.5)(utf-8-validate@5.0.10))(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat-deploy-ethers@0.3.0-beta.13(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + version: 2.0.3(ethereum-waffle@3.4.4(bufferutil@4.0.8)(encoding@0.1.13)(typescript@5.5.4)(utf-8-validate@5.0.10))(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat-deploy-ethers@0.3.0-beta.13(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10)))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10)) '@tenderly/hardhat-tenderly': specifier: 1.3.2 - version: 1.3.2(bufferutil@4.0.8)(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))(tenderly@0.0.3(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5))(utf-8-validate@5.0.10) + version: 1.3.2(bufferutil@4.0.8)(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10))(tenderly@0.0.3(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4))(utf-8-validate@5.0.10) '@typechain/hardhat': specifier: 6.1.4 - version: 6.1.4(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(@typechain/ethers-v5@10.2.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.4.5))(typescript@5.4.5))(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.4.5)) + version: 6.1.4(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(@typechain/ethers-v5@10.2.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.5.4))(typescript@5.5.4))(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.5.4)) dotenv: specifier: 16.3.1 version: 16.3.1 @@ -903,14 +903,14 @@ importers: version: 0.11.22(bufferutil@4.0.8)(utf-8-validate@5.0.10) hardhat-deploy-ethers: specifier: 0.3.0-beta.13 - version: 0.3.0-beta.13(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + version: 0.3.0-beta.13(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10)) devDependencies: ethers: specifier: 5.7.2 version: 5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) hardhat: specifier: 2.20.1 - version: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) + version: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10) config/jest: dependencies: @@ -920,7 +920,7 @@ importers: devDependencies: '@types/node': specifier: '20' - version: 20.10.0 + version: 20.14.14 config/nextjs: devDependencies: @@ -932,23 +932,23 @@ importers: dependencies: '@tailwindcss/aspect-ratio': specifier: 0.4.2 - version: 0.4.2(tailwindcss@3.3.2(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))) + version: 0.4.2(tailwindcss@3.3.2(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))) '@tailwindcss/forms': specifier: 0.5.3 - version: 0.5.3(tailwindcss@3.3.2(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))) + version: 0.5.3(tailwindcss@3.3.2(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))) '@tailwindcss/typography': specifier: 0.5.9 - version: 0.5.9(tailwindcss@3.3.2(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))) + version: 0.5.9(tailwindcss@3.3.2(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))) tailwindcss-animate: specifier: 1.0.7 - version: 1.0.7(tailwindcss@3.3.2(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))) + version: 1.0.7(tailwindcss@3.3.2(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))) devDependencies: '@types/node': specifier: '20' - version: 20.10.0 + version: 20.14.14 tailwindcss: specifier: 3.3.2 - version: 3.3.2(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)) + version: 3.3.2(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4)) config/typescript: {} @@ -968,7 +968,7 @@ importers: version: 2.13.1(@tanstack/query-core@5.51.16)(@types/react@18.2.14)(immer@9.0.21)(react@18.2.0)(typescript@5.4.5)(viem@2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@6.0.3)(zod@3.23.8)) jest: specifier: 29.7.0 - version: 29.7.0(@types/node@20.12.7)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5)) + version: 29.7.0(@types/node@22.1.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5)) sushi: specifier: workspace:* version: link:../../packages/sushi @@ -1097,13 +1097,13 @@ importers: version: 29.5.5 '@types/node': specifier: '20' - version: 20.10.0 + version: 20.14.14 jest: specifier: 29.7.0 - version: 29.7.0(@types/node@20.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)) + version: 29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5)) ts-jest: specifier: 29.1.1 - version: 29.1.1(@babel/core@7.24.4)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.4))(jest@29.7.0(@types/node@20.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)))(typescript@5.4.5) + version: 29.1.1(@babel/core@7.24.4)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.4))(jest@29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5)))(typescript@5.4.5) typescript: specifier: 5.4.5 version: 5.4.5 @@ -1158,7 +1158,7 @@ importers: version: 2.0.2 '@types/node': specifier: '20' - version: 20.10.0 + version: 20.14.14 react: specifier: 18.2.0 version: 18.2.0 @@ -1167,7 +1167,7 @@ importers: version: 2.1.5(react@18.2.0) tsup: specifier: 7.2.0 - version: 7.2.0(@swc/core@1.4.2)(postcss@8.4.31)(ts-node@10.9.2(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5) + version: 7.2.0(@swc/core@1.4.2)(postcss@8.4.31)(ts-node@10.9.2(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5) typescript: specifier: 5.4.5 version: 5.4.5 @@ -1195,13 +1195,13 @@ importers: version: 29.5.5 '@types/node': specifier: '20' - version: 20.10.0 + version: 20.14.14 dotenv: specifier: 16.3.1 version: 16.3.1 jest: specifier: 29.7.0 - version: 29.7.0(@types/node@20.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)) + version: 29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5)) prisma: specifier: 5.6.0 version: 5.6.0 @@ -1250,10 +1250,10 @@ importers: version: 2.0.2 '@types/node': specifier: '20' - version: 20.10.0 + version: 20.14.14 jest: specifier: 29.7.0 - version: 29.7.0(@types/node@20.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)) + version: 29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5)) typescript: specifier: 5.4.5 version: 5.4.5 @@ -1302,7 +1302,7 @@ importers: version: 1.0.4 '@types/node': specifier: '20' - version: 20.12.7 + version: 20.14.14 tsc-alias: specifier: ^1.8.10 version: 1.8.10 @@ -1345,7 +1345,7 @@ importers: version: 18.2.6 jest: specifier: 29.7.0 - version: 29.7.0(@types/node@20.12.7)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5)) + version: 29.7.0(@types/node@22.1.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5)) react: specifier: 18.2.0 version: 18.2.0 @@ -1357,7 +1357,7 @@ importers: version: link:../sushi tailwindcss: specifier: 3.3.2 - version: 3.3.2(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5)) + version: 3.3.2(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5)) typescript: specifier: 5.4.5 version: 5.4.5 @@ -1458,7 +1458,7 @@ importers: version: 18.2.6 jest: specifier: 29.7.0 - version: 29.7.0(@types/node@20.12.7)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5)) + version: 29.7.0(@types/node@22.1.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5)) next: specifier: 14.2.3 version: 14.2.3(@babel/core@7.24.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.45.0)(babel-plugin-macros@3.1.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) @@ -1485,7 +1485,7 @@ importers: dependencies: '@steerprotocol/contracts': specifier: 2.1.0-beta.14 - version: 2.1.0-beta.14(bufferutil@4.0.8)(encoding@0.1.13)(squirrelly@8.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) + version: 2.1.0-beta.14(bufferutil@4.0.8)(encoding@0.1.13)(squirrelly@8.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) '@sushiswap/database': specifier: workspace:* version: link:../database @@ -1514,7 +1514,7 @@ importers: version: 2.0.2 '@types/node': specifier: '20' - version: 20.10.0 + version: 20.14.14 '@wagmi/core': specifier: 2.13.1 version: 2.13.1(@tanstack/query-core@5.51.16)(@types/react@18.2.14)(immer@9.0.21)(react@18.2.0)(typescript@5.4.5)(viem@2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8)) @@ -1586,6 +1586,10 @@ importers: specifier: 3.23.8 version: 3.23.8 + packages/sushi/dist/_cjs: {} + + packages/sushi/dist/_esm: {} + packages/telemetry: devDependencies: '@tsconfig/esm': @@ -1704,13 +1708,13 @@ importers: version: link:../telemetry '@tailwindcss/aspect-ratio': specifier: 0.4.2 - version: 0.4.2(tailwindcss@3.3.2(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))) + version: 0.4.2(tailwindcss@3.3.2(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5))) '@tailwindcss/forms': specifier: 0.5.3 - version: 0.5.3(tailwindcss@3.3.2(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))) + version: 0.5.3(tailwindcss@3.3.2(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5))) '@tailwindcss/typography': specifier: 0.5.9 - version: 0.5.9(tailwindcss@3.3.2(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))) + version: 0.5.9(tailwindcss@3.3.2(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5))) '@tanstack/react-table': specifier: 8.9.1 version: 8.9.1(react-dom@18.2.0(react@18.2.0))(react@18.2.0) @@ -1764,7 +1768,7 @@ importers: version: 1.13.2 tailwindcss-animate: specifier: 1.0.7 - version: 1.0.7(tailwindcss@3.3.2(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))) + version: 1.0.7(tailwindcss@3.3.2(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5))) use-resize-observer: specifier: 9.1.0 version: 9.1.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0) @@ -1813,7 +1817,7 @@ importers: version: link:../sushi tailwindcss: specifier: 3.3.2 - version: 3.3.2(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)) + version: 3.3.2(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5)) typescript: specifier: 5.4.5 version: 5.4.5 @@ -1834,19 +1838,19 @@ importers: version: 5.7.0 '@nomicfoundation/hardhat-network-helpers': specifier: 1.0.8 - version: 1.0.8(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + version: 1.0.8(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) '@nomiclabs/hardhat-ethers': specifier: npm:hardhat-deploy-ethers@^0.3.0-beta.13 - version: hardhat-deploy-ethers@0.3.0-beta.13(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + version: hardhat-deploy-ethers@0.3.0-beta.13(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) '@nomiclabs/hardhat-etherscan': specifier: 3.1.3 - version: 3.1.3(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + version: 3.1.3(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) '@nomiclabs/hardhat-solhint': specifier: 2.0.1 - version: 2.0.1(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + version: 2.0.1(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) '@nomiclabs/hardhat-waffle': specifier: 2.0.3 - version: 2.0.3(ethereum-waffle@3.4.4(bufferutil@4.0.8)(encoding@0.1.13)(typescript@5.4.5)(utf-8-validate@5.0.10))(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat-deploy-ethers@0.3.0-beta.13(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + version: 2.0.3(ethereum-waffle@3.4.4(bufferutil@4.0.8)(encoding@0.1.13)(typescript@5.4.5)(utf-8-validate@5.0.10))(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat-deploy-ethers@0.3.0-beta.13(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) '@openzeppelin/contracts': specifier: 4.8.0 version: 4.8.0 @@ -1870,7 +1874,7 @@ importers: version: 9.1.1 '@types/node': specifier: '20' - version: 20.10.0 + version: 20.14.14 '@types/seedrandom': specifier: 3.0.8 version: 3.0.8 @@ -1891,28 +1895,28 @@ importers: version: 5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) hardhat: specifier: 2.20.1 - version: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) + version: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) hardhat-contract-sizer: specifier: 2.10.0 - version: 2.10.0(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + version: 2.10.0(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) hardhat-deploy: specifier: 0.11.22 version: 0.11.22(bufferutil@4.0.8)(utf-8-validate@5.0.10) hardhat-gas-reporter: specifier: 1.0.9 - version: 1.0.9(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + version: 1.0.9(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) hardhat-log-remover: specifier: 2.0.2 - version: 2.0.2(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + version: 2.0.2(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) hardhat-preprocessor: specifier: 0.1.5 - version: 0.1.5(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + version: 0.1.5(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) hardhat-spdx-license-identifier: specifier: 2.1.0 - version: 2.1.0(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + version: 2.1.0(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) hardhat-watcher: specifier: 2.5.0 - version: 2.5.0(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + version: 2.5.0(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) mocha: specifier: ^10.2.0 version: 10.2.0 @@ -1930,7 +1934,7 @@ importers: version: 0.3.0 solidity-coverage: specifier: 0.8.2 - version: 0.8.2(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + version: 0.8.2(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) sushi: specifier: workspace:* version: link:../../packages/sushi @@ -1939,7 +1943,7 @@ importers: version: 0.1.1 ts-node: specifier: 10.9.1 - version: 10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5) + version: 10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5) typescript: specifier: 5.4.5 version: 5.4.5 @@ -1969,19 +1973,19 @@ importers: version: 5.7.0 '@nomicfoundation/hardhat-network-helpers': specifier: 1.0.8 - version: 1.0.8(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + version: 1.0.8(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) '@nomiclabs/hardhat-ethers': specifier: npm:hardhat-deploy-ethers@^0.3.0-beta.13 - version: hardhat-deploy-ethers@0.3.0-beta.13(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + version: hardhat-deploy-ethers@0.3.0-beta.13(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) '@nomiclabs/hardhat-etherscan': specifier: 3.1.3 - version: 3.1.3(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + version: 3.1.3(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) '@nomiclabs/hardhat-solhint': specifier: 2.0.1 - version: 2.0.1(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + version: 2.0.1(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) '@nomiclabs/hardhat-waffle': specifier: 2.0.3 - version: 2.0.3(ethereum-waffle@3.4.4(bufferutil@4.0.8)(encoding@0.1.13)(typescript@5.4.5)(utf-8-validate@5.0.10))(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat-deploy-ethers@0.3.0-beta.13(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + version: 2.0.3(ethereum-waffle@3.4.4(bufferutil@4.0.8)(encoding@0.1.13)(typescript@5.4.5)(utf-8-validate@5.0.10))(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat-deploy-ethers@0.3.0-beta.13(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) '@openzeppelin/contracts': specifier: 4.8.0 version: 4.8.0 @@ -2005,7 +2009,7 @@ importers: version: 9.1.1 '@types/node': specifier: '20' - version: 20.10.0 + version: 20.14.14 '@types/seedrandom': specifier: 3.0.8 version: 3.0.8 @@ -2032,28 +2036,28 @@ importers: version: 5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) hardhat: specifier: 2.20.1 - version: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) + version: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) hardhat-contract-sizer: specifier: 2.6.1 - version: 2.6.1(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + version: 2.6.1(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) hardhat-deploy: specifier: 0.11.22 version: 0.11.22(bufferutil@4.0.8)(utf-8-validate@5.0.10) hardhat-gas-reporter: specifier: 1.0.9 - version: 1.0.9(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + version: 1.0.9(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) hardhat-log-remover: specifier: 2.0.2 - version: 2.0.2(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + version: 2.0.2(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) hardhat-preprocessor: specifier: 0.1.5 - version: 0.1.5(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + version: 0.1.5(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) hardhat-spdx-license-identifier: specifier: 2.1.0 - version: 2.1.0(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + version: 2.1.0(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) hardhat-watcher: specifier: 2.5.0 - version: 2.5.0(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + version: 2.5.0(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) mocha: specifier: ^10.2.0 version: 10.2.0 @@ -2068,7 +2072,7 @@ importers: version: 3.0.5 solidity-coverage: specifier: 0.8.2 - version: 0.8.2(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + version: 0.8.2(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) sushi: specifier: workspace:* version: link:../../packages/sushi @@ -2077,10 +2081,10 @@ importers: version: 0.1.1 ts-node: specifier: 10.9.1 - version: 10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5) + version: 10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5) tsup: specifier: 7.2.0 - version: 7.2.0(@swc/core@1.4.2)(postcss@8.4.31)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5) + version: 7.2.0(@swc/core@1.4.2)(postcss@8.4.31)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5) typescript: specifier: 5.4.5 version: 5.4.5 @@ -8961,11 +8965,11 @@ packages: '@types/node@18.11.18': resolution: {integrity: sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==} - '@types/node@20.10.0': - resolution: {integrity: sha512-D0WfRmU9TQ8I9PFx9Yc+EBHw+vSpIub4IDvQivcp26PtPrdMGAq5SDcpXEo/epqa/DXotVpekHiLNTg3iaKXBQ==} + '@types/node@20.14.14': + resolution: {integrity: sha512-d64f00982fS9YoOgJkAMolK7MN8Iq3TDdVjchbYHdEmjth/DHowx82GnoA+tVUAN+7vxfYUgAzi+JXbKNd2SDQ==} - '@types/node@20.12.7': - resolution: {integrity: sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==} + '@types/node@22.1.0': + resolution: {integrity: sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw==} '@types/node@8.10.66': resolution: {integrity: sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==} @@ -9474,8 +9478,8 @@ packages: typescript: optional: true - '@viem/anvil@0.0.7': - resolution: {integrity: sha512-F+3ljCT1bEt8T4Fzm9gWpIgO3Dc7bzG1TtUtkStkJFMuummqZ8kvYc3UFMo5j3F51fSWZZvEkjs3+i7qf0AOqQ==} + '@viem/anvil@0.0.10': + resolution: {integrity: sha512-9PzYXBRikfSUhhm8Bd0avv07agwcbMJ5FaSu2D2vbE0cxkvXGtolL3fW5nz2yefMqOqVQL4XzfM5nwY81x3ytw==} '@vitejs/plugin-react@3.1.0': resolution: {integrity: sha512-AfgcRL8ZBhAlc3BFdigClmTUMISmmzHn7sB2h9U1odvc5U/MjWXsAaz18b/WoppUTDBzxOJwo2VdClfUcItu9g==} @@ -11586,8 +11590,8 @@ packages: resolution: {integrity: sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==} deprecated: core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js. - core-js@3.37.0: - resolution: {integrity: sha512-fu5vHevQ8ZG4og+LXug8ulUtVxjOcEYvifJr7L5Bfq9GOztVqsKd9/59hUk2ZSbCrS3BqUr3EpaYGIYzq7g3Ug==} + core-js@3.38.0: + resolution: {integrity: sha512-XPpwqEodRljce9KswjZShh95qJ1URisBeKCjUdq27YdenkslVe7OO0ZJhlYXAChW7OhXaRLl8AAba7IBfoIHug==} core-util-is@1.0.2: resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==} @@ -17329,8 +17333,8 @@ packages: resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} engines: {node: '>=8'} - npm-run-path@5.1.0: - resolution: {integrity: sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==} + npm-run-path@5.3.0: + resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} npmlog@5.0.1: @@ -21446,6 +21450,11 @@ packages: engines: {node: '>=14.17'} hasBin: true + typescript@5.5.4: + resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==} + engines: {node: '>=14.17'} + hasBin: true + typewise-core@1.2.0: resolution: {integrity: sha512-2SCC/WLzj2SbUwzFOzqMCkz5amXLlxtJqDKTICqg30x+2DZxcfZN2MvQZmGfXWKNWaKK9pBPsvkcwv8bF/gxKg==} @@ -21504,6 +21513,9 @@ packages: undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + undici-types@6.13.0: + resolution: {integrity: sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==} + undici@5.23.0: resolution: {integrity: sha512-1D7w+fvRsqlQ9GscLBwcAJinqcZGHUKjbOmXdlE/v8BvEGXjeWAax+341q44EuTcHXXnfyKNbKRq4Lg7OzhMmg==} engines: {node: '>=14.0'} @@ -23013,14 +23025,14 @@ snapshots: transitivePeerDependencies: - debug - '@aptstats/aptos-wallet-framework@0.0.2(@babel/plugin-syntax-flow@7.24.1(@babel/core@7.24.4))(@babel/plugin-transform-react-jsx@7.23.4(@babel/core@7.24.4))(@types/babel__core@7.20.5)(aptos@1.21.0)(bufferutil@4.0.8)(eslint@8.57.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))(type-fest@4.18.3)(typescript@5.4.5)(utf-8-validate@5.0.10)(vue-template-compiler@2.7.16)': + '@aptstats/aptos-wallet-framework@0.0.2(@babel/plugin-syntax-flow@7.24.1(@babel/core@7.24.4))(@babel/plugin-transform-react-jsx@7.23.4(@babel/core@7.24.4))(@types/babel__core@7.20.5)(aptos@1.21.0)(bufferutil@4.0.8)(eslint@8.57.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5))(type-fest@4.18.3)(typescript@5.4.5)(utf-8-validate@5.0.10)(vue-template-compiler@2.7.16)': dependencies: aptos: 1.21.0 eventemitter3: 4.0.7 js-sha3: 0.8.0 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - react-scripts: 5.0.1(@babel/plugin-syntax-flow@7.24.1(@babel/core@7.24.4))(@babel/plugin-transform-react-jsx@7.23.4(@babel/core@7.24.4))(@types/babel__core@7.20.5)(bufferutil@4.0.8)(eslint@8.57.0)(react@18.2.0)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))(type-fest@4.18.3)(typescript@5.4.5)(utf-8-validate@5.0.10)(vue-template-compiler@2.7.16) + react-scripts: 5.0.1(@babel/plugin-syntax-flow@7.24.1(@babel/core@7.24.4))(@babel/plugin-transform-react-jsx@7.23.4(@babel/core@7.24.4))(@types/babel__core@7.20.5)(bufferutil@4.0.8)(eslint@8.57.0)(react@18.2.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5))(type-fest@4.18.3)(typescript@5.4.5)(utf-8-validate@5.0.10)(vue-template-compiler@2.7.16) transitivePeerDependencies: - '@babel/plugin-syntax-flow' - '@babel/plugin-transform-react-jsx' @@ -23057,14 +23069,14 @@ snapshots: - webpack-hot-middleware - webpack-plugin-serve - '@aptstats/aptos-wallet-framework@0.0.6(@babel/plugin-syntax-flow@7.24.1(@babel/core@7.24.4))(@babel/plugin-transform-react-jsx@7.23.4(@babel/core@7.24.4))(@types/babel__core@7.20.5)(aptos@1.21.0)(bufferutil@4.0.8)(eslint@8.57.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))(type-fest@4.18.3)(typescript@5.4.5)(utf-8-validate@5.0.10)(vue-template-compiler@2.7.16)': + '@aptstats/aptos-wallet-framework@0.0.6(@babel/plugin-syntax-flow@7.24.1(@babel/core@7.24.4))(@babel/plugin-transform-react-jsx@7.23.4(@babel/core@7.24.4))(@types/babel__core@7.20.5)(aptos@1.21.0)(bufferutil@4.0.8)(eslint@8.57.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5))(type-fest@4.18.3)(typescript@5.4.5)(utf-8-validate@5.0.10)(vue-template-compiler@2.7.16)': dependencies: aptos: 1.21.0 eventemitter3: 4.0.7 js-sha3: 0.8.0 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - react-scripts: 5.0.1(@babel/plugin-syntax-flow@7.24.1(@babel/core@7.24.4))(@babel/plugin-transform-react-jsx@7.23.4(@babel/core@7.24.4))(@types/babel__core@7.20.5)(bufferutil@4.0.8)(eslint@8.57.0)(react@18.2.0)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))(type-fest@4.18.3)(typescript@5.4.5)(utf-8-validate@5.0.10)(vue-template-compiler@2.7.16) + react-scripts: 5.0.1(@babel/plugin-syntax-flow@7.24.1(@babel/core@7.24.4))(@babel/plugin-transform-react-jsx@7.23.4(@babel/core@7.24.4))(@types/babel__core@7.20.5)(bufferutil@4.0.8)(eslint@8.57.0)(react@18.2.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5))(type-fest@4.18.3)(typescript@5.4.5)(utf-8-validate@5.0.10)(vue-template-compiler@2.7.16) transitivePeerDependencies: - '@babel/plugin-syntax-flow' - '@babel/plugin-transform-react-jsx' @@ -23101,9 +23113,9 @@ snapshots: - webpack-hot-middleware - webpack-plugin-serve - '@aptstats/safepal-wallet-extension@0.0.3(@babel/plugin-syntax-flow@7.24.1(@babel/core@7.24.4))(@babel/plugin-transform-react-jsx@7.23.4(@babel/core@7.24.4))(@types/babel__core@7.20.5)(aptos@1.21.0)(bufferutil@4.0.8)(eslint@8.57.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))(type-fest@4.18.3)(typescript@5.4.5)(utf-8-validate@5.0.10)(vue-template-compiler@2.7.16)': + '@aptstats/safepal-wallet-extension@0.0.3(@babel/plugin-syntax-flow@7.24.1(@babel/core@7.24.4))(@babel/plugin-transform-react-jsx@7.23.4(@babel/core@7.24.4))(@types/babel__core@7.20.5)(aptos@1.21.0)(bufferutil@4.0.8)(eslint@8.57.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5))(type-fest@4.18.3)(typescript@5.4.5)(utf-8-validate@5.0.10)(vue-template-compiler@2.7.16)': dependencies: - '@aptstats/aptos-wallet-framework': 0.0.2(@babel/plugin-syntax-flow@7.24.1(@babel/core@7.24.4))(@babel/plugin-transform-react-jsx@7.23.4(@babel/core@7.24.4))(@types/babel__core@7.20.5)(aptos@1.21.0)(bufferutil@4.0.8)(eslint@8.57.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))(type-fest@4.18.3)(typescript@5.4.5)(utf-8-validate@5.0.10)(vue-template-compiler@2.7.16) + '@aptstats/aptos-wallet-framework': 0.0.2(@babel/plugin-syntax-flow@7.24.1(@babel/core@7.24.4))(@babel/plugin-transform-react-jsx@7.23.4(@babel/core@7.24.4))(@types/babel__core@7.20.5)(aptos@1.21.0)(bufferutil@4.0.8)(eslint@8.57.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5))(type-fest@4.18.3)(typescript@5.4.5)(utf-8-validate@5.0.10)(vue-template-compiler@2.7.16) aptos: 1.21.0 eventemitter3: 4.0.7 transitivePeerDependencies: @@ -23198,10 +23210,10 @@ snapshots: '@assemblyscript/loader@0.19.23': {} - '@atixlabs/hardhat-time-n-mine@0.0.5(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))': + '@atixlabs/hardhat-time-n-mine@0.0.5(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))': dependencies: '@types/ms': 0.7.31 - hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) + hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) ms: 2.1.2 '@aw-web-design/x-default-browser@1.4.126': @@ -26392,6 +26404,26 @@ snapshots: - typescript - utf-8-validate + '@ethereum-waffle/compiler@3.4.4(bufferutil@4.0.8)(encoding@0.1.13)(typescript@5.5.4)(utf-8-validate@5.0.10)': + dependencies: + '@resolver-engine/imports': 0.3.3 + '@resolver-engine/imports-fs': 0.3.3 + '@typechain/ethers-v5': 2.0.0(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(typechain@3.0.0(typescript@5.5.4)) + '@types/mkdirp': 0.5.2 + '@types/node-fetch': 2.6.11 + ethers: 5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) + mkdirp: 0.5.6 + node-fetch: 2.7.0(encoding@0.1.13) + solc: 0.6.12 + ts-generator: 0.1.1 + typechain: 3.0.0(typescript@5.5.4) + transitivePeerDependencies: + - bufferutil + - encoding + - supports-color + - typescript + - utf-8-validate + '@ethereum-waffle/ens@3.4.4(bufferutil@4.0.8)(utf-8-validate@5.0.10)': dependencies: '@ensdomains/ens': 0.4.5 @@ -26815,7 +26847,7 @@ snapshots: '@grpc/grpc-js@1.9.2': dependencies: '@grpc/proto-loader': 0.7.9 - '@types/node': 20.12.7 + '@types/node': 20.14.14 '@grpc/proto-loader@0.7.9': dependencies: @@ -26886,7 +26918,7 @@ snapshots: '@jest/console@27.5.1': dependencies: '@jest/types': 27.5.1 - '@types/node': 20.12.7 + '@types/node': 22.1.0 chalk: 4.1.2 jest-message-util: 27.5.1 jest-util: 27.5.1 @@ -26895,7 +26927,7 @@ snapshots: '@jest/console@28.1.3': dependencies: '@jest/types': 28.1.3 - '@types/node': 20.12.7 + '@types/node': 22.1.0 chalk: 4.1.2 jest-message-util: 28.1.3 jest-util: 28.1.3 @@ -26904,27 +26936,27 @@ snapshots: '@jest/console@29.7.0': dependencies: '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 22.1.0 chalk: 4.1.2 jest-message-util: 29.7.0 jest-util: 29.7.0 slash: 3.0.0 - '@jest/core@27.5.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))(utf-8-validate@5.0.10)': + '@jest/core@27.5.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5))(utf-8-validate@5.0.10)': dependencies: '@jest/console': 27.5.1 '@jest/reporters': 27.5.1 '@jest/test-result': 27.5.1 '@jest/transform': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 20.12.7 + '@types/node': 22.1.0 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.8.1 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 27.5.1 - jest-config: 27.5.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))(utf-8-validate@5.0.10) + jest-config: 27.5.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5))(utf-8-validate@5.0.10) jest-haste-map: 27.5.1 jest-message-util: 27.5.1 jest-regex-util: 27.5.1 @@ -26947,21 +26979,56 @@ snapshots: - ts-node - utf-8-validate - '@jest/core@29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))': + '@jest/core@29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5))': + dependencies: + '@jest/console': 29.7.0 + '@jest/reporters': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 22.1.0 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + ci-info: 3.8.0 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-changed-files: 29.7.0 + jest-config: 29.7.0(@types/node@22.1.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5)) + jest-haste-map: 29.7.0 + jest-message-util: 29.7.0 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-resolve-dependencies: 29.7.0 + jest-runner: 29.7.0 + jest-runtime: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + jest-watcher: 29.7.0 + micromatch: 4.0.5 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-ansi: 6.0.1 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + - ts-node + + '@jest/core@29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))': dependencies: '@jest/console': 29.7.0 '@jest/reporters': 29.7.0 '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 22.1.0 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.8.0 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@20.12.7)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)) + jest-config: 29.7.0(@types/node@22.1.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4)) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -26982,21 +27049,21 @@ snapshots: - supports-color - ts-node - '@jest/core@29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))': + '@jest/core@29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5))': dependencies: '@jest/console': 29.7.0 '@jest/reporters': 29.7.0 '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 22.1.0 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.8.0 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@20.12.7)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5)) + jest-config: 29.7.0(@types/node@22.1.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5)) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -27025,14 +27092,14 @@ snapshots: dependencies: '@jest/fake-timers': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 20.12.7 + '@types/node': 22.1.0 jest-mock: 27.5.1 '@jest/environment@29.7.0': dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 20.14.14 jest-mock: 29.7.0 '@jest/expect-utils@29.7.0': @@ -27050,7 +27117,7 @@ snapshots: dependencies: '@jest/types': 27.5.1 '@sinonjs/fake-timers': 8.1.0 - '@types/node': 20.12.7 + '@types/node': 22.1.0 jest-message-util: 27.5.1 jest-mock: 27.5.1 jest-util: 27.5.1 @@ -27059,7 +27126,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 20.12.7 + '@types/node': 20.14.14 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -27086,7 +27153,7 @@ snapshots: '@jest/test-result': 27.5.1 '@jest/transform': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 20.12.7 + '@types/node': 22.1.0 chalk: 4.1.2 collect-v8-coverage: 1.0.2 exit: 0.1.2 @@ -27117,7 +27184,7 @@ snapshots: '@jest/transform': 29.7.0 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.19 - '@types/node': 20.12.7 + '@types/node': 22.1.0 chalk: 4.1.2 collect-v8-coverage: 1.0.2 exit: 0.1.2 @@ -27239,7 +27306,7 @@ snapshots: dependencies: '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 20.12.7 + '@types/node': 22.1.0 '@types/yargs': 15.0.19 chalk: 4.1.2 @@ -27247,7 +27314,7 @@ snapshots: dependencies: '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 20.12.7 + '@types/node': 22.1.0 '@types/yargs': 16.0.9 chalk: 4.1.2 @@ -27256,7 +27323,7 @@ snapshots: '@jest/schemas': 28.1.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 20.12.7 + '@types/node': 22.1.0 '@types/yargs': 17.0.24 chalk: 4.1.2 @@ -27265,17 +27332,17 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.4 '@types/istanbul-reports': 3.0.1 - '@types/node': 20.12.7 + '@types/node': 20.14.14 '@types/yargs': 17.0.24 chalk: 4.1.2 - '@joshwooding/vite-plugin-react-docgen-typescript@0.2.1(typescript@5.4.5)(vite@4.3.9(@types/node@20.12.7)(less@4.2.0)(terser@5.30.3))': + '@joshwooding/vite-plugin-react-docgen-typescript@0.2.1(typescript@5.4.5)(vite@4.3.9(@types/node@22.1.0)(less@4.2.0)(terser@5.30.3))': dependencies: glob: 7.2.3 glob-promise: 4.2.2(glob@7.2.3) magic-string: 0.27.0 react-docgen-typescript: 2.2.2(typescript@5.4.5) - vite: 4.3.9(@types/node@20.12.7)(less@4.2.0)(terser@5.30.3) + vite: 4.3.9(@types/node@22.1.0)(less@4.2.0)(terser@5.30.3) optionalDependencies: typescript: 5.4.5 @@ -27411,19 +27478,19 @@ snapshots: transitivePeerDependencies: - debug - '@matterlabs/hardhat-zksync-deploy@0.6.2(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))(zksync-web3@0.13.4(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10)))': + '@matterlabs/hardhat-zksync-deploy@0.6.2(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10))(zksync-web3@0.13.4(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10)))': dependencies: chalk: 4.1.2 ethers: 5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) - hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) + hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10) zksync-web3: 0.13.4(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10)) - '@matterlabs/hardhat-zksync-solc@0.3.14(encoding@0.1.13)(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))': + '@matterlabs/hardhat-zksync-solc@0.3.14(encoding@0.1.13)(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10))': dependencies: '@nomiclabs/hardhat-docker': 2.0.2(encoding@0.1.13) chalk: 4.1.2 dockerode: 3.3.5 - hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) + hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10) transitivePeerDependencies: - encoding - supports-color @@ -28040,10 +28107,10 @@ snapshots: - c-kzg - supports-color - '@nomicfoundation/hardhat-network-helpers@1.0.8(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))': + '@nomicfoundation/hardhat-network-helpers@1.0.8(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))': dependencies: ethereumjs-util: 7.1.5 - hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) + hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) '@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.1': optional: true @@ -28097,7 +28164,7 @@ snapshots: - encoding - supports-color - '@nomiclabs/hardhat-etherscan@3.1.3(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))': + '@nomiclabs/hardhat-etherscan@3.1.3(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))': dependencies: '@ethersproject/abi': 5.7.0 '@ethersproject/address': 5.7.0 @@ -28105,7 +28172,7 @@ snapshots: chalk: 2.4.2 debug: 4.3.4(supports-color@8.1.1) fs-extra: 7.0.1 - hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) + hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) lodash: 4.17.21 semver: 6.3.1 table: 6.8.1 @@ -28113,7 +28180,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@nomiclabs/hardhat-etherscan@3.1.3(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))': + '@nomiclabs/hardhat-etherscan@3.1.3(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10))': dependencies: '@ethersproject/abi': 5.7.0 '@ethersproject/address': 5.7.0 @@ -28121,7 +28188,7 @@ snapshots: chalk: 2.4.2 debug: 4.3.4(supports-color@8.1.1) fs-extra: 7.0.1 - hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) + hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10) lodash: 4.17.21 semver: 6.3.1 table: 6.8.1 @@ -28129,37 +28196,37 @@ snapshots: transitivePeerDependencies: - supports-color - '@nomiclabs/hardhat-solhint@2.0.1(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))': + '@nomiclabs/hardhat-solhint@2.0.1(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))': dependencies: - hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) + hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) solhint: 2.3.1 transitivePeerDependencies: - supports-color - '@nomiclabs/hardhat-solhint@2.0.1(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))': + '@nomiclabs/hardhat-solhint@2.0.1(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10))': dependencies: - hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) + hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10) solhint: 2.3.1 transitivePeerDependencies: - supports-color - '@nomiclabs/hardhat-waffle@2.0.3(ethereum-waffle@3.4.4(bufferutil@4.0.8)(encoding@0.1.13)(typescript@5.4.5)(utf-8-validate@5.0.10))(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat-deploy-ethers@0.3.0-beta.13(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))': + '@nomiclabs/hardhat-waffle@2.0.3(ethereum-waffle@3.4.4(bufferutil@4.0.8)(encoding@0.1.13)(typescript@5.4.5)(utf-8-validate@5.0.10))(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat-deploy-ethers@0.3.0-beta.13(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))': dependencies: - '@nomiclabs/hardhat-ethers': hardhat-deploy-ethers@0.3.0-beta.13(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + '@nomiclabs/hardhat-ethers': hardhat-deploy-ethers@0.3.0-beta.13(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) '@types/sinon-chai': 3.2.9 '@types/web3': 1.0.19 ethereum-waffle: 3.4.4(bufferutil@4.0.8)(encoding@0.1.13)(typescript@5.4.5)(utf-8-validate@5.0.10) ethers: 5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) - hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) + hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) - '@nomiclabs/hardhat-waffle@2.0.3(ethereum-waffle@3.4.4(bufferutil@4.0.8)(encoding@0.1.13)(typescript@5.4.5)(utf-8-validate@5.0.10))(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat-deploy-ethers@0.3.0-beta.13(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))': + '@nomiclabs/hardhat-waffle@2.0.3(ethereum-waffle@3.4.4(bufferutil@4.0.8)(encoding@0.1.13)(typescript@5.5.4)(utf-8-validate@5.0.10))(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat-deploy-ethers@0.3.0-beta.13(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10)))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10))': dependencies: - '@nomiclabs/hardhat-ethers': hardhat-deploy-ethers@0.3.0-beta.13(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + '@nomiclabs/hardhat-ethers': hardhat-deploy-ethers@0.3.0-beta.13(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10)) '@types/sinon-chai': 3.2.9 '@types/web3': 1.0.19 - ethereum-waffle: 3.4.4(bufferutil@4.0.8)(encoding@0.1.13)(typescript@5.4.5)(utf-8-validate@5.0.10) + ethereum-waffle: 3.4.4(bufferutil@4.0.8)(encoding@0.1.13)(typescript@5.5.4)(utf-8-validate@5.0.10) ethers: 5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) - hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) + hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10) '@npmcli/config@6.4.0': dependencies: @@ -28189,7 +28256,7 @@ snapshots: supports-color: 8.1.1 tslib: 2.6.3 - '@oclif/core@2.11.8(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5)': + '@oclif/core@2.11.8(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5)': dependencies: '@types/cli-progress': 3.11.0 ansi-escapes: 4.3.2 @@ -28216,7 +28283,7 @@ snapshots: strip-ansi: 6.0.1 supports-color: 8.1.1 supports-hyperlinks: 2.3.0 - ts-node: 10.9.2(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5) + ts-node: 10.9.2(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5) tslib: 2.6.2 widest-line: 3.1.0 wordwrap: 1.0.0 @@ -28227,19 +28294,19 @@ snapshots: - '@types/node' - typescript - '@oclif/plugin-help@5.2.17(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5)': + '@oclif/plugin-help@5.2.17(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5)': dependencies: - '@oclif/core': 2.11.8(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5) + '@oclif/core': 2.11.8(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5) transitivePeerDependencies: - '@swc/core' - '@swc/wasm' - '@types/node' - typescript - '@oclif/plugin-not-found@2.3.37(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5)': + '@oclif/plugin-not-found@2.3.37(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5)': dependencies: '@oclif/color': 1.0.10 - '@oclif/core': 2.11.8(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5) + '@oclif/core': 2.11.8(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5) fast-levenshtein: 3.0.0 transitivePeerDependencies: - '@swc/core' @@ -29015,9 +29082,9 @@ snapshots: '@popperjs/core@2.11.7': {} - '@primitivefi/hardhat-dodoc@0.2.3(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))(squirrelly@8.0.8)': + '@primitivefi/hardhat-dodoc@0.2.3(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))(squirrelly@8.0.8)': dependencies: - hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) + hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) squirrelly: 8.0.8 '@prisma/client@5.6.0(prisma@5.6.0)': @@ -31372,17 +31439,17 @@ snapshots: '@stablelib/random': 1.0.2 '@stablelib/wipe': 1.0.1 - '@steerprotocol/contracts@2.1.0-beta.14(bufferutil@4.0.8)(encoding@0.1.13)(squirrelly@8.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)': + '@steerprotocol/contracts@2.1.0-beta.14(bufferutil@4.0.8)(encoding@0.1.13)(squirrelly@8.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)': dependencies: - '@atixlabs/hardhat-time-n-mine': 0.0.5(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + '@atixlabs/hardhat-time-n-mine': 0.0.5(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) '@pancakeswap/v3-core': 1.0.2 '@pancakeswap/v3-periphery': 1.0.2 - '@primitivefi/hardhat-dodoc': 0.2.3(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))(squirrelly@8.0.8) - '@uniswap/v3-sdk': 3.10.0(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + '@primitivefi/hardhat-dodoc': 0.2.3(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))(squirrelly@8.0.8) + '@uniswap/v3-sdk': 3.10.0(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) ethereumjs-util: 7.1.5 execa: 5.1.1 fs-extra: 10.1.0 - hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) + hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) patch-package: 6.5.1 web3: 1.10.3(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10) web3-eth-abi: 1.10.3 @@ -31750,7 +31817,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@storybook/builder-vite@7.4.6(typescript@5.4.5)(vite@4.3.9(@types/node@20.12.7)(less@4.2.0)(terser@5.30.3))': + '@storybook/builder-vite@7.4.6(typescript@5.4.5)(vite@4.3.9(@types/node@22.1.0)(less@4.2.0)(terser@5.30.3))': dependencies: '@storybook/channels': 7.4.6 '@storybook/client-logger': 7.4.6 @@ -31771,7 +31838,7 @@ snapshots: remark-external-links: 8.0.0 remark-slug: 6.1.0 rollup: 3.28.0 - vite: 4.3.9(@types/node@20.12.7)(less@4.2.0)(terser@5.30.3) + vite: 4.3.9(@types/node@22.1.0)(less@4.2.0)(terser@5.30.3) optionalDependencies: typescript: 5.4.5 transitivePeerDependencies: @@ -32202,19 +32269,19 @@ snapshots: react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - '@storybook/react-vite@7.4.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(rollup@3.29.4)(typescript@5.4.5)(vite@4.3.9(@types/node@20.12.7)(less@4.2.0)(terser@5.30.3))': + '@storybook/react-vite@7.4.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(rollup@3.29.4)(typescript@5.4.5)(vite@4.3.9(@types/node@22.1.0)(less@4.2.0)(terser@5.30.3))': dependencies: - '@joshwooding/vite-plugin-react-docgen-typescript': 0.2.1(typescript@5.4.5)(vite@4.3.9(@types/node@20.12.7)(less@4.2.0)(terser@5.30.3)) + '@joshwooding/vite-plugin-react-docgen-typescript': 0.2.1(typescript@5.4.5)(vite@4.3.9(@types/node@22.1.0)(less@4.2.0)(terser@5.30.3)) '@rollup/pluginutils': 5.0.4(rollup@3.29.4) - '@storybook/builder-vite': 7.4.6(typescript@5.4.5)(vite@4.3.9(@types/node@20.12.7)(less@4.2.0)(terser@5.30.3)) + '@storybook/builder-vite': 7.4.6(typescript@5.4.5)(vite@4.3.9(@types/node@22.1.0)(less@4.2.0)(terser@5.30.3)) '@storybook/react': 7.4.6(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.4.5) - '@vitejs/plugin-react': 3.1.0(vite@4.3.9(@types/node@20.12.7)(less@4.2.0)(terser@5.30.3)) + '@vitejs/plugin-react': 3.1.0(vite@4.3.9(@types/node@22.1.0)(less@4.2.0)(terser@5.30.3)) ast-types: 0.14.2 magic-string: 0.30.2 react: 18.2.0 react-docgen: 6.0.0-alpha.3 react-dom: 18.2.0(react@18.2.0) - vite: 4.3.9(@types/node@20.12.7)(less@4.2.0)(terser@5.30.3) + vite: 4.3.9(@types/node@22.1.0)(less@4.2.0)(terser@5.30.3) transitivePeerDependencies: - '@preact/preset-vite' - rollup @@ -32488,22 +32555,39 @@ snapshots: dependencies: defer-to-connect: 2.0.1 - '@tailwindcss/aspect-ratio@0.4.2(tailwindcss@3.3.2(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)))': + '@tailwindcss/aspect-ratio@0.4.2(tailwindcss@3.3.2(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5)))': + dependencies: + tailwindcss: 3.3.2(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5)) + + '@tailwindcss/aspect-ratio@0.4.2(tailwindcss@3.3.2(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4)))': + dependencies: + tailwindcss: 3.3.2(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4)) + + '@tailwindcss/forms@0.5.3(tailwindcss@3.3.2(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5)))': dependencies: - tailwindcss: 3.3.2(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)) + mini-svg-data-uri: 1.4.4 + tailwindcss: 3.3.2(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5)) - '@tailwindcss/forms@0.5.3(tailwindcss@3.3.2(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)))': + '@tailwindcss/forms@0.5.3(tailwindcss@3.3.2(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4)))': dependencies: mini-svg-data-uri: 1.4.4 - tailwindcss: 3.3.2(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)) + tailwindcss: 3.3.2(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4)) + + '@tailwindcss/typography@0.5.9(tailwindcss@3.3.2(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5)))': + dependencies: + lodash.castarray: 4.4.0 + lodash.isplainobject: 4.0.6 + lodash.merge: 4.6.2 + postcss-selector-parser: 6.0.10 + tailwindcss: 3.3.2(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5)) - '@tailwindcss/typography@0.5.9(tailwindcss@3.3.2(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)))': + '@tailwindcss/typography@0.5.9(tailwindcss@3.3.2(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4)))': dependencies: lodash.castarray: 4.4.0 lodash.isplainobject: 4.0.6 lodash.merge: 4.6.2 postcss-selector-parser: 6.0.10 - tailwindcss: 3.3.2(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)) + tailwindcss: 3.3.2(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4)) '@tanstack/match-sorter-utils@8.8.4': dependencies: @@ -32544,17 +32628,17 @@ snapshots: '@tanstack/table-core@8.9.1': {} - '@tenderly/hardhat-tenderly@1.3.2(bufferutil@4.0.8)(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))(tenderly@0.0.3(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5))(utf-8-validate@5.0.10)': + '@tenderly/hardhat-tenderly@1.3.2(bufferutil@4.0.8)(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10))(tenderly@0.0.3(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4))(utf-8-validate@5.0.10)': dependencies: '@ethersproject/bignumber': 5.7.0 - '@nomiclabs/hardhat-ethers': hardhat-deploy-ethers@0.3.0-beta.13(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + '@nomiclabs/hardhat-ethers': hardhat-deploy-ethers@0.3.0-beta.13(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10)) axios: 0.27.2(debug@4.3.4) ethers: 5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) fs-extra: 10.1.0 - hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) + hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10) hardhat-deploy: 0.11.22(bufferutil@4.0.8)(utf-8-validate@5.0.10) js-yaml: 4.1.0 - tenderly: 0.0.3(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5) + tenderly: 0.0.3(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4) transitivePeerDependencies: - bufferutil - debug @@ -32600,34 +32684,39 @@ snapshots: '@tsconfig/strictest@2.0.2': {} - '@typechain/ethers-v5@10.2.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.4.5))(typescript@5.4.5)': + '@typechain/ethers-v5@10.2.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.5.4))(typescript@5.5.4)': dependencies: '@ethersproject/abi': 5.7.0 '@ethersproject/providers': 5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) ethers: 5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) lodash: 4.17.21 - ts-essentials: 7.0.3(typescript@5.4.5) - typechain: 8.3.2(typescript@5.4.5) - typescript: 5.4.5 + ts-essentials: 7.0.3(typescript@5.5.4) + typechain: 8.3.2(typescript@5.5.4) + typescript: 5.5.4 '@typechain/ethers-v5@2.0.0(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(typechain@3.0.0(typescript@5.4.5))': dependencies: ethers: 5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) typechain: 3.0.0(typescript@5.4.5) - '@typechain/hardhat@6.1.4(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(@typechain/ethers-v5@10.2.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.4.5))(typescript@5.4.5))(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.4.5))': + '@typechain/ethers-v5@2.0.0(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(typechain@3.0.0(typescript@5.5.4))': + dependencies: + ethers: 5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) + typechain: 3.0.0(typescript@5.5.4) + + '@typechain/hardhat@6.1.4(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(@typechain/ethers-v5@10.2.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.5.4))(typescript@5.5.4))(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.5.4))': dependencies: '@ethersproject/abi': 5.7.0 '@ethersproject/providers': 5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) - '@typechain/ethers-v5': 10.2.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.4.5))(typescript@5.4.5) + '@typechain/ethers-v5': 10.2.1(@ethersproject/abi@5.7.0)(@ethersproject/providers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.5.4))(typescript@5.5.4) ethers: 5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) fs-extra: 9.1.0 - hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) - typechain: 8.3.2(typescript@5.4.5) + hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10) + typechain: 8.3.2(typescript@5.5.4) '@types/accepts@1.3.7': dependencies: - '@types/node': 20.12.7 + '@types/node': 22.1.0 '@types/acorn@4.0.6': dependencies: @@ -32689,20 +32778,20 @@ snapshots: '@types/bn.js@4.11.6': dependencies: - '@types/node': 20.12.7 + '@types/node': 22.1.0 '@types/bn.js@5.1.1': dependencies: - '@types/node': 20.12.7 + '@types/node': 22.1.0 '@types/body-parser@1.19.2': dependencies: '@types/connect': 3.4.35 - '@types/node': 20.12.7 + '@types/node': 20.14.14 '@types/bonjour@3.5.13': dependencies: - '@types/node': 20.12.7 + '@types/node': 22.1.0 '@types/btoa-lite@1.0.0': {} @@ -32710,7 +32799,7 @@ snapshots: dependencies: '@types/http-cache-semantics': 4.0.1 '@types/keyv': 3.1.4 - '@types/node': 20.12.7 + '@types/node': 20.14.14 '@types/responselike': 1.0.0 '@types/chai-subset@1.3.3': @@ -32721,20 +32810,20 @@ snapshots: '@types/cli-progress@3.11.0': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.14 '@types/concat-stream@1.6.1': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.14 '@types/concat-stream@2.0.0': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.14 '@types/connect-history-api-fallback@1.5.4': dependencies: '@types/express-serve-static-core': 4.17.35 - '@types/node': 20.12.7 + '@types/node': 22.1.0 '@types/connect-timeout@0.0.36': dependencies: @@ -32742,11 +32831,11 @@ snapshots: '@types/connect@3.4.35': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.14 '@types/connect@3.4.36': dependencies: - '@types/node': 20.12.7 + '@types/node': 22.1.0 '@types/content-disposition@0.5.8': {} @@ -32755,15 +32844,15 @@ snapshots: '@types/connect': 3.4.36 '@types/express': 4.17.17 '@types/keygrip': 1.0.6 - '@types/node': 20.12.7 + '@types/node': 22.1.0 '@types/cors@2.8.13': dependencies: - '@types/node': 20.10.0 + '@types/node': 20.14.14 '@types/cross-spawn@6.0.2': dependencies: - '@types/node': 20.12.7 + '@types/node': 22.1.0 '@types/d3-array@3.0.5': {} @@ -32930,7 +33019,7 @@ snapshots: '@types/express-serve-static-core@4.17.35': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.14 '@types/qs': 6.9.8 '@types/range-parser': 1.2.4 '@types/send': 0.17.1 @@ -32953,18 +33042,18 @@ snapshots: '@types/form-data@0.0.33': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.14 '@types/geojson@7946.0.10': {} '@types/glob@7.2.0': dependencies: '@types/minimatch': 5.1.2 - '@types/node': 20.12.7 + '@types/node': 20.14.14 '@types/graceful-fs@4.1.6': dependencies: - '@types/node': 20.12.7 + '@types/node': 22.1.0 '@types/gtag.js@0.0.19': {} @@ -32982,7 +33071,7 @@ snapshots: '@types/http-proxy@1.17.14': dependencies: - '@types/node': 20.12.7 + '@types/node': 22.1.0 '@types/is-ci@3.0.0': dependencies: @@ -33019,7 +33108,7 @@ snapshots: '@types/jsdom@20.0.1': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.14 '@types/tough-cookie': 4.0.2 parse5: 7.1.2 @@ -33033,13 +33122,13 @@ snapshots: '@types/jsonwebtoken@9.0.2': dependencies: - '@types/node': 20.12.7 + '@types/node': 22.1.0 '@types/keygrip@1.0.6': {} '@types/keyv@3.1.4': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.14 '@types/koa-compose@3.2.8': dependencies: @@ -33054,7 +33143,7 @@ snapshots: '@types/http-errors': 2.0.1 '@types/keygrip': 1.0.6 '@types/koa-compose': 3.2.8 - '@types/node': 20.12.7 + '@types/node': 22.1.0 '@types/koa__router@12.0.3': dependencies: @@ -33108,7 +33197,7 @@ snapshots: '@types/mkdirp@0.5.2': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.14 '@types/mocha@9.1.1': {} @@ -33118,21 +33207,21 @@ snapshots: '@types/mysql@2.15.22': dependencies: - '@types/node': 20.12.7 + '@types/node': 22.1.0 '@types/node-fetch@2.6.11': dependencies: - '@types/node': 20.12.7 + '@types/node': 22.1.0 form-data: 4.0.0 '@types/node-fetch@2.6.4': dependencies: - '@types/node': 20.12.7 + '@types/node': 22.1.0 form-data: 3.0.1 '@types/node-forge@1.3.11': dependencies: - '@types/node': 20.12.7 + '@types/node': 22.1.0 '@types/node@10.17.60': {} @@ -33146,13 +33235,13 @@ snapshots: '@types/node@18.11.18': {} - '@types/node@20.10.0': + '@types/node@20.14.14': dependencies: undici-types: 5.26.5 - '@types/node@20.12.7': + '@types/node@22.1.0': dependencies: - undici-types: 5.26.5 + undici-types: 6.13.0 '@types/node@8.10.66': {} @@ -33162,7 +33251,7 @@ snapshots: '@types/pbkdf2@3.1.0': dependencies: - '@types/node': 20.12.7 + '@types/node': 22.1.0 '@types/pg-pool@2.0.4': dependencies: @@ -33170,13 +33259,13 @@ snapshots: '@types/pg@8.6.1': dependencies: - '@types/node': 20.12.7 + '@types/node': 22.1.0 pg-protocol: 1.6.0 pg-types: 2.2.0 '@types/pg@8.6.6': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.14 pg-protocol: 1.6.0 pg-types: 2.2.0 @@ -33236,22 +33325,22 @@ snapshots: '@types/readable-stream@2.3.15': dependencies: - '@types/node': 20.12.7 + '@types/node': 22.1.0 safe-buffer: 5.1.2 '@types/resolve@0.0.8': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.14 '@types/resolve@1.17.1': dependencies: - '@types/node': 20.12.7 + '@types/node': 22.1.0 '@types/resolve@1.20.2': {} '@types/responselike@1.0.0': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.14 '@types/retry@0.12.0': {} @@ -33259,11 +33348,11 @@ snapshots: '@types/secp256k1@4.0.3': dependencies: - '@types/node': 20.12.7 + '@types/node': 22.1.0 '@types/secp256k1@4.0.6': dependencies: - '@types/node': 20.12.7 + '@types/node': 22.1.0 '@types/seedrandom@3.0.1': {} @@ -33274,7 +33363,7 @@ snapshots: '@types/send@0.17.1': dependencies: '@types/mime': 1.3.2 - '@types/node': 20.12.7 + '@types/node': 20.14.14 '@types/serve-index@1.9.4': dependencies: @@ -33284,7 +33373,7 @@ snapshots: dependencies: '@types/http-errors': 2.0.1 '@types/mime': 3.0.1 - '@types/node': 20.12.7 + '@types/node': 20.14.14 '@types/shimmer@1.0.5': {} @@ -33301,7 +33390,7 @@ snapshots: '@types/sockjs@0.3.36': dependencies: - '@types/node': 20.12.7 + '@types/node': 22.1.0 '@types/stack-utils@2.0.1': {} @@ -33328,11 +33417,11 @@ snapshots: '@types/ws@7.4.7': dependencies: - '@types/node': 20.12.7 + '@types/node': 22.1.0 '@types/ws@8.5.5': dependencies: - '@types/node': 20.12.7 + '@types/node': 22.1.0 '@types/yargs-parser@21.0.0': {} @@ -33542,14 +33631,14 @@ snapshots: tiny-invariant: 1.3.1 toformat: 2.0.0 - '@uniswap/swap-router-contracts@1.3.0(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))': + '@uniswap/swap-router-contracts@1.3.0(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))': dependencies: '@openzeppelin/contracts': 3.4.2-solc-0.7 '@uniswap/v2-core': 1.0.1 '@uniswap/v3-core': 1.0.0 - '@uniswap/v3-periphery': 1.4.1(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + '@uniswap/v3-periphery': 1.4.1(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) dotenv: 14.3.2 - hardhat-watcher: 2.5.0(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + hardhat-watcher: 2.5.0(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) transitivePeerDependencies: - hardhat @@ -33561,14 +33650,14 @@ snapshots: '@uniswap/v3-core@1.0.1': {} - '@uniswap/v3-periphery@1.4.1(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))': + '@uniswap/v3-periphery@1.4.1(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))': dependencies: '@openzeppelin/contracts': 3.4.2-solc-0.7 '@uniswap/lib': 4.0.1-alpha '@uniswap/v2-core': 1.0.1 '@uniswap/v3-core': 1.0.0 base64-sol: 1.0.1 - hardhat-watcher: 2.5.0(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + hardhat-watcher: 2.5.0(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) transitivePeerDependencies: - hardhat @@ -33588,12 +33677,12 @@ snapshots: '@uniswap/v3-core': 1.0.1 base64-sol: 1.0.1 - '@uniswap/v3-sdk@3.10.0(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))': + '@uniswap/v3-sdk@3.10.0(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10))': dependencies: '@ethersproject/abi': 5.7.0 '@ethersproject/solidity': 5.7.0 '@uniswap/sdk-core': 4.0.9 - '@uniswap/swap-router-contracts': 1.3.0(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) + '@uniswap/swap-router-contracts': 1.3.0(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) '@uniswap/v3-periphery': 1.4.4 '@uniswap/v3-staker': 1.0.0 tiny-invariant: 1.3.1 @@ -33857,7 +33946,7 @@ snapshots: json-schema-to-ts: 1.6.4 ts-morph: 12.0.0 - '@vercel/style-guide@5.0.1(eslint@8.57.0)(jest@29.7.0(@types/node@20.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)))(typescript@5.4.5)': + '@vercel/style-guide@5.0.1(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4)))(typescript@5.4.5)': dependencies: '@babel/core': 7.23.2 '@babel/eslint-parser': 7.22.15(@babel/core@7.23.2)(eslint@8.57.0) @@ -33869,9 +33958,9 @@ snapshots: eslint-import-resolver-typescript: 3.6.0(@typescript-eslint/parser@6.7.5(eslint@8.57.0)(typescript@5.4.5))(eslint-plugin-import@2.28.1)(eslint@8.57.0) eslint-plugin-eslint-comments: 3.2.0(eslint@8.57.0) eslint-plugin-import: 2.28.1(@typescript-eslint/parser@6.7.5(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0) - eslint-plugin-jest: 27.4.2(@typescript-eslint/eslint-plugin@6.7.5(@typescript-eslint/parser@6.7.5(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)))(typescript@5.4.5) + eslint-plugin-jest: 27.4.2(@typescript-eslint/eslint-plugin@6.7.5(@typescript-eslint/parser@6.7.5(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4)))(typescript@5.4.5) eslint-plugin-jsx-a11y: 6.7.1(eslint@8.57.0) - eslint-plugin-playwright: 0.16.0(eslint-plugin-jest@27.4.2(@typescript-eslint/eslint-plugin@6.7.5(@typescript-eslint/parser@6.7.5(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)))(typescript@5.4.5))(eslint@8.57.0) + eslint-plugin-playwright: 0.16.0(eslint-plugin-jest@27.4.2(@typescript-eslint/eslint-plugin@6.7.5(@typescript-eslint/parser@6.7.5(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4)))(typescript@5.4.5))(eslint@8.57.0) eslint-plugin-react: 7.33.2(eslint@8.57.0) eslint-plugin-react-hooks: 4.6.0(eslint@8.57.0) eslint-plugin-testing-library: 6.1.0(eslint@8.57.0)(typescript@5.4.5) @@ -33887,7 +33976,7 @@ snapshots: - jest - supports-color - '@viem/anvil@0.0.7(bufferutil@4.0.8)(utf-8-validate@5.0.10)': + '@viem/anvil@0.0.10(bufferutil@4.0.8)(utf-8-validate@5.0.10)': dependencies: execa: 7.2.0 get-port: 6.1.2 @@ -33898,25 +33987,25 @@ snapshots: - debug - utf-8-validate - '@vitejs/plugin-react@3.1.0(vite@4.3.9(@types/node@20.12.7)(less@4.2.0)(terser@5.30.3))': + '@vitejs/plugin-react@3.1.0(vite@4.3.9(@types/node@22.1.0)(less@4.2.0)(terser@5.30.3))': dependencies: '@babel/core': 7.23.2 '@babel/plugin-transform-react-jsx-self': 7.22.5(@babel/core@7.23.2) '@babel/plugin-transform-react-jsx-source': 7.22.5(@babel/core@7.23.2) magic-string: 0.27.0 react-refresh: 0.14.0 - vite: 4.3.9(@types/node@20.12.7)(less@4.2.0)(terser@5.30.3) + vite: 4.3.9(@types/node@22.1.0)(less@4.2.0)(terser@5.30.3) transitivePeerDependencies: - supports-color - '@vitejs/plugin-react@4.1.0(vite@4.3.9(@types/node@20.12.7)(less@4.2.0)(terser@5.30.3))': + '@vitejs/plugin-react@4.1.0(vite@4.3.9(@types/node@22.1.0)(less@4.2.0)(terser@5.30.3))': dependencies: '@babel/core': 7.23.2 '@babel/plugin-transform-react-jsx-self': 7.22.5(@babel/core@7.23.2) '@babel/plugin-transform-react-jsx-source': 7.22.5(@babel/core@7.23.2) '@types/babel__core': 7.20.2 react-refresh: 0.14.0 - vite: 4.3.9(@types/node@20.12.7)(less@4.2.0)(terser@5.30.3) + vite: 4.3.9(@types/node@22.1.0)(less@4.2.0)(terser@5.30.3) transitivePeerDependencies: - supports-color @@ -35547,14 +35636,14 @@ snapshots: - supports-color - utf-8-validate - artillery@2.0.5(@swc/core@1.4.2)(@types/node@20.10.0)(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10): + artillery@2.0.5(@swc/core@1.4.2)(@types/node@20.14.14)(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10): dependencies: '@artilleryio/int-commons': 2.0.4 '@artilleryio/int-core': 2.3.1(bufferutil@4.0.8)(utf-8-validate@5.0.10) '@aws-sdk/credential-providers': 3.391.0 - '@oclif/core': 2.11.8(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5) - '@oclif/plugin-help': 5.2.17(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5) - '@oclif/plugin-not-found': 2.3.37(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5) + '@oclif/core': 2.11.8(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5) + '@oclif/plugin-help': 5.2.17(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5) + '@oclif/plugin-not-found': 2.3.37(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5) archiver: 5.3.2 artillery-engine-playwright: 1.3.0 artillery-plugin-apdex: 1.0.1 @@ -37112,7 +37201,7 @@ snapshots: chrome-launcher@0.15.2: dependencies: - '@types/node': 20.12.7 + '@types/node': 22.1.0 escape-string-regexp: 4.0.0 is-wsl: 2.2.0 lighthouse-logger: 1.4.2 @@ -37123,7 +37212,7 @@ snapshots: chromium-edge-launcher@1.0.0: dependencies: - '@types/node': 20.12.7 + '@types/node': 22.1.0 escape-string-regexp: 4.0.0 is-wsl: 2.2.0 lighthouse-logger: 1.4.2 @@ -37537,7 +37626,7 @@ snapshots: core-js@2.6.12: {} - core-js@3.37.0: {} + core-js@3.38.0: {} core-util-is@1.0.2: {} @@ -37621,13 +37710,13 @@ snapshots: safe-buffer: 5.2.1 sha.js: 2.4.11 - create-jest@29.7.0(@types/node@20.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)): + create-jest@29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5)): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@20.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)) + jest-config: 29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5)) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -37636,13 +37725,28 @@ snapshots: - supports-color - ts-node - create-jest@29.7.0(@types/node@20.12.7)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5)): + create-jest@29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4)): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@20.12.7)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5)) + jest-config: 29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4)) + jest-util: 29.7.0 + prompts: 2.4.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + + create-jest@29.7.0(@types/node@22.1.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5)): + dependencies: + '@jest/types': 29.6.3 + chalk: 4.1.2 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-config: 29.7.0(@types/node@22.1.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5)) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -39281,7 +39385,7 @@ snapshots: dependencies: eslint: 8.57.0 - eslint-config-react-app@7.0.1(@babel/plugin-syntax-flow@7.24.1(@babel/core@7.24.4))(@babel/plugin-transform-react-jsx@7.23.4(@babel/core@7.24.4))(eslint@8.57.0)(jest@27.5.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))(utf-8-validate@5.0.10))(typescript@5.4.5): + eslint-config-react-app@7.0.1(@babel/plugin-syntax-flow@7.24.1(@babel/core@7.24.4))(@babel/plugin-transform-react-jsx@7.23.4(@babel/core@7.24.4))(eslint@8.57.0)(jest@27.5.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5))(utf-8-validate@5.0.10))(typescript@5.4.5): dependencies: '@babel/core': 7.24.4 '@babel/eslint-parser': 7.22.15(@babel/core@7.24.4)(eslint@8.57.0) @@ -39293,7 +39397,7 @@ snapshots: eslint: 8.57.0 eslint-plugin-flowtype: 8.0.3(@babel/plugin-syntax-flow@7.24.1(@babel/core@7.24.4))(@babel/plugin-transform-react-jsx@7.23.4(@babel/core@7.24.4))(eslint@8.57.0) eslint-plugin-import: 2.28.1(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0) - eslint-plugin-jest: 25.7.0(@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@27.5.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))(utf-8-validate@5.0.10))(typescript@5.4.5) + eslint-plugin-jest: 25.7.0(@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@27.5.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5))(utf-8-validate@5.0.10))(typescript@5.4.5) eslint-plugin-jsx-a11y: 6.7.1(eslint@8.57.0) eslint-plugin-react: 7.33.2(eslint@8.57.0) eslint-plugin-react-hooks: 4.6.0(eslint@8.57.0) @@ -39511,24 +39615,24 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-plugin-jest@25.7.0(@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@27.5.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))(utf-8-validate@5.0.10))(typescript@5.4.5): + eslint-plugin-jest@25.7.0(@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@27.5.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5))(utf-8-validate@5.0.10))(typescript@5.4.5): dependencies: '@typescript-eslint/experimental-utils': 5.62.0(eslint@8.57.0)(typescript@5.4.5) eslint: 8.57.0 optionalDependencies: '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5) - jest: 27.5.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))(utf-8-validate@5.0.10) + jest: 27.5.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5))(utf-8-validate@5.0.10) transitivePeerDependencies: - supports-color - typescript - eslint-plugin-jest@27.4.2(@typescript-eslint/eslint-plugin@6.7.5(@typescript-eslint/parser@6.7.5(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)))(typescript@5.4.5): + eslint-plugin-jest@27.4.2(@typescript-eslint/eslint-plugin@6.7.5(@typescript-eslint/parser@6.7.5(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4)))(typescript@5.4.5): dependencies: '@typescript-eslint/utils': 5.62.0(eslint@8.57.0)(typescript@5.4.5) eslint: 8.57.0 optionalDependencies: '@typescript-eslint/eslint-plugin': 6.7.5(@typescript-eslint/parser@6.7.5(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5) - jest: 29.7.0(@types/node@20.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)) + jest: 29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4)) transitivePeerDependencies: - supports-color - typescript @@ -39576,11 +39680,11 @@ snapshots: eslint-plugin-only-warn@1.1.0: {} - eslint-plugin-playwright@0.16.0(eslint-plugin-jest@27.4.2(@typescript-eslint/eslint-plugin@6.7.5(@typescript-eslint/parser@6.7.5(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)))(typescript@5.4.5))(eslint@8.57.0): + eslint-plugin-playwright@0.16.0(eslint-plugin-jest@27.4.2(@typescript-eslint/eslint-plugin@6.7.5(@typescript-eslint/parser@6.7.5(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4)))(typescript@5.4.5))(eslint@8.57.0): dependencies: eslint: 8.57.0 optionalDependencies: - eslint-plugin-jest: 27.4.2(@typescript-eslint/eslint-plugin@6.7.5(@typescript-eslint/parser@6.7.5(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)))(typescript@5.4.5) + eslint-plugin-jest: 27.4.2(@typescript-eslint/eslint-plugin@6.7.5(@typescript-eslint/parser@6.7.5(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(jest@29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4)))(typescript@5.4.5) eslint-plugin-react-hooks@4.6.0(eslint@8.57.0): dependencies: @@ -40090,6 +40194,20 @@ snapshots: - typescript - utf-8-validate + ethereum-waffle@3.4.4(bufferutil@4.0.8)(encoding@0.1.13)(typescript@5.5.4)(utf-8-validate@5.0.10): + dependencies: + '@ethereum-waffle/chai': 3.4.4(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10) + '@ethereum-waffle/compiler': 3.4.4(bufferutil@4.0.8)(encoding@0.1.13)(typescript@5.5.4)(utf-8-validate@5.0.10) + '@ethereum-waffle/mock-contract': 3.4.4(bufferutil@4.0.8)(utf-8-validate@5.0.10) + '@ethereum-waffle/provider': 3.4.4(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10) + ethers: 5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) + transitivePeerDependencies: + - bufferutil + - encoding + - supports-color + - typescript + - utf-8-validate + ethereumjs-abi@0.6.5: dependencies: bn.js: 4.12.0 @@ -40388,7 +40506,7 @@ snapshots: human-signals: 4.3.1 is-stream: 3.0.0 merge-stream: 2.0.0 - npm-run-path: 5.1.0 + npm-run-path: 5.3.0 onetime: 6.0.0 signal-exit: 3.0.7 strip-final-newline: 3.0.0 @@ -41455,28 +41573,28 @@ snapshots: hard-rejection@2.1.0: {} - hardhat-contract-sizer@2.10.0(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)): + hardhat-contract-sizer@2.10.0(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)): dependencies: chalk: 4.1.2 cli-table3: 0.6.3 - hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) + hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) strip-ansi: 6.0.1 - hardhat-contract-sizer@2.6.1(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)): + hardhat-contract-sizer@2.6.1(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)): dependencies: chalk: 4.1.2 cli-table3: 0.6.3 - hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) + hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) - hardhat-deploy-ethers@0.3.0-beta.13(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)): + hardhat-deploy-ethers@0.3.0-beta.13(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)): dependencies: ethers: 5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) - hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) + hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) - hardhat-deploy-ethers@0.3.0-beta.13(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)): + hardhat-deploy-ethers@0.3.0-beta.13(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10)): dependencies: ethers: 5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10) - hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) + hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10) hardhat-deploy@0.11.22(bufferutil@4.0.8)(utf-8-validate@5.0.10): dependencies: @@ -41498,39 +41616,39 @@ snapshots: - supports-color - utf-8-validate - hardhat-gas-reporter@1.0.9(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)): + hardhat-gas-reporter@1.0.9(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)): dependencies: array-uniq: 1.0.3 eth-gas-reporter: 0.2.25 - hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) + hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) sha1: 1.1.1 transitivePeerDependencies: - '@codechecks/client' - hardhat-log-remover@2.0.2(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)): + hardhat-log-remover@2.0.2(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)): dependencies: - hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) + hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) - hardhat-preprocessor@0.1.5(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)): + hardhat-preprocessor@0.1.5(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)): dependencies: - hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) + hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) murmur-128: 0.2.1 - hardhat-spdx-license-identifier@2.1.0(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)): + hardhat-spdx-license-identifier@2.1.0(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)): dependencies: - hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) + hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) - hardhat-watcher@2.5.0(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)): + hardhat-watcher@2.5.0(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)): dependencies: chokidar: 3.5.3 - hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) + hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) - hardhat-watcher@2.5.0(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)): + hardhat-watcher@2.5.0(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)): dependencies: chokidar: 3.5.3 - hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) + hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) - hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10): + hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10): dependencies: '@ethersproject/abi': 5.7.0 '@metamask/eth-sig-util': 4.0.1 @@ -41583,7 +41701,7 @@ snapshots: uuid: 8.3.2 ws: 7.5.9(bufferutil@4.0.8)(utf-8-validate@5.0.10) optionalDependencies: - ts-node: 10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5) + ts-node: 10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5) typescript: 5.4.5 transitivePeerDependencies: - bufferutil @@ -41591,7 +41709,7 @@ snapshots: - supports-color - utf-8-validate - hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10): + hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10): dependencies: '@ethersproject/abi': 5.7.0 '@metamask/eth-sig-util': 4.0.1 @@ -41644,7 +41762,7 @@ snapshots: uuid: 8.3.2 ws: 7.5.9(bufferutil@4.0.8)(utf-8-validate@5.0.10) optionalDependencies: - ts-node: 10.9.2(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5) + ts-node: 10.9.2(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5) typescript: 5.4.5 transitivePeerDependencies: - bufferutil @@ -41652,6 +41770,67 @@ snapshots: - supports-color - utf-8-validate + hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4)(utf-8-validate@5.0.10): + dependencies: + '@ethersproject/abi': 5.7.0 + '@metamask/eth-sig-util': 4.0.1 + '@nomicfoundation/ethereumjs-block': 5.0.4 + '@nomicfoundation/ethereumjs-blockchain': 7.0.4 + '@nomicfoundation/ethereumjs-common': 4.0.4 + '@nomicfoundation/ethereumjs-evm': 2.0.4(@nomicfoundation/ethereumjs-verkle@0.0.2) + '@nomicfoundation/ethereumjs-rlp': 5.0.4 + '@nomicfoundation/ethereumjs-statemanager': 2.0.4(@nomicfoundation/ethereumjs-verkle@0.0.2) + '@nomicfoundation/ethereumjs-trie': 6.0.4 + '@nomicfoundation/ethereumjs-tx': 5.0.4 + '@nomicfoundation/ethereumjs-util': 9.0.4 + '@nomicfoundation/ethereumjs-verkle': 0.0.2 + '@nomicfoundation/ethereumjs-vm': 7.0.4(@nomicfoundation/ethereumjs-verkle@0.0.2) + '@nomicfoundation/solidity-analyzer': 0.1.1 + '@sentry/node': 5.30.0 + '@types/bn.js': 5.1.1 + '@types/lru-cache': 5.1.1 + adm-zip: 0.4.16 + aggregate-error: 3.1.0 + ansi-escapes: 4.3.2 + boxen: 5.1.2 + chalk: 2.4.2 + chokidar: 3.5.3 + ci-info: 2.0.0 + debug: 4.3.4(supports-color@8.1.1) + enquirer: 2.4.1 + env-paths: 2.2.1 + ethereum-cryptography: 1.2.0 + ethereumjs-abi: 0.6.8 + find-up: 2.1.0 + fp-ts: 1.19.3 + fs-extra: 7.0.1 + glob: 7.2.0 + immutable: 4.3.2 + io-ts: 1.10.4 + keccak: 3.0.3 + lodash: 4.17.21 + mnemonist: 0.38.5 + mocha: 10.2.0 + p-map: 4.0.0 + raw-body: 2.5.2 + resolve: 1.17.0 + semver: 6.3.1 + solc: 0.7.3(debug@4.3.4) + source-map-support: 0.5.21 + stacktrace-parser: 0.1.10 + tsort: 0.0.1 + undici: 5.26.5 + uuid: 8.3.2 + ws: 7.5.9(bufferutil@4.0.8)(utf-8-validate@5.0.10) + optionalDependencies: + ts-node: 10.9.2(@types/node@20.14.14)(typescript@5.5.4) + typescript: 5.5.4 + transitivePeerDependencies: + - bufferutil + - c-kzg + - supports-color + - utf-8-validate + harmony-reflect@1.6.2: {} has-ansi@2.0.0: @@ -42652,7 +42831,7 @@ snapshots: '@jest/environment': 27.5.1 '@jest/test-result': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 20.12.7 + '@types/node': 22.1.0 chalk: 4.1.2 co: 4.6.0 dedent: 0.7.0 @@ -42677,7 +42856,7 @@ snapshots: '@jest/expect': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 22.1.0 chalk: 4.1.2 co: 4.6.0 dedent: 1.5.1(babel-plugin-macros@3.1.0) @@ -42697,16 +42876,16 @@ snapshots: - babel-plugin-macros - supports-color - jest-cli@27.5.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))(utf-8-validate@5.0.10): + jest-cli@27.5.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5))(utf-8-validate@5.0.10): dependencies: - '@jest/core': 27.5.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))(utf-8-validate@5.0.10) + '@jest/core': 27.5.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5))(utf-8-validate@5.0.10) '@jest/test-result': 27.5.1 '@jest/types': 27.5.1 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 import-local: 3.1.0 - jest-config: 27.5.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))(utf-8-validate@5.0.10) + jest-config: 27.5.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5))(utf-8-validate@5.0.10) jest-util: 27.5.1 jest-validate: 27.5.1 prompts: 2.4.2 @@ -42718,16 +42897,35 @@ snapshots: - ts-node - utf-8-validate - jest-cli@29.7.0(@types/node@20.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)): + jest-cli@29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5)): + dependencies: + '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5)) + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + chalk: 4.1.2 + create-jest: 29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5)) + exit: 0.1.2 + import-local: 3.1.0 + jest-config: 29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5)) + jest-util: 29.7.0 + jest-validate: 29.7.0 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + + jest-cli@29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4)): dependencies: - '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)) + '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4)) '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@20.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)) + create-jest: 29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4)) exit: 0.1.2 import-local: 3.1.0 - jest-config: 29.7.0(@types/node@20.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)) + jest-config: 29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4)) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -42737,16 +42935,16 @@ snapshots: - supports-color - ts-node - jest-cli@29.7.0(@types/node@20.12.7)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5)): + jest-cli@29.7.0(@types/node@22.1.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5)): dependencies: - '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5)) + '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5)) '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@20.12.7)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5)) + create-jest: 29.7.0(@types/node@22.1.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5)) exit: 0.1.2 import-local: 3.1.0 - jest-config: 29.7.0(@types/node@20.12.7)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5)) + jest-config: 29.7.0(@types/node@22.1.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5)) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -42756,7 +42954,7 @@ snapshots: - supports-color - ts-node - jest-config@27.5.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))(utf-8-validate@5.0.10): + jest-config@27.5.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5))(utf-8-validate@5.0.10): dependencies: '@babel/core': 7.24.4 '@jest/test-sequencer': 27.5.1 @@ -42783,14 +42981,45 @@ snapshots: slash: 3.0.0 strip-json-comments: 3.1.1 optionalDependencies: - ts-node: 10.9.2(@types/node@20.12.7)(typescript@5.4.5) + ts-node: 10.9.2(@types/node@22.1.0)(typescript@5.4.5) transitivePeerDependencies: - bufferutil - canvas - supports-color - utf-8-validate - jest-config@29.7.0(@types/node@20.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)): + jest-config@29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5)): + dependencies: + '@babel/core': 7.22.10 + '@jest/test-sequencer': 29.7.0 + '@jest/types': 29.6.3 + babel-jest: 29.7.0(@babel/core@7.22.10) + chalk: 4.1.2 + ci-info: 3.8.0 + deepmerge: 4.3.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-circus: 29.7.0(babel-plugin-macros@3.1.0) + jest-environment-node: 29.7.0 + jest-get-type: 29.6.3 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-runner: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + micromatch: 4.0.5 + parse-json: 5.2.0 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-json-comments: 3.1.1 + optionalDependencies: + '@types/node': 20.14.14 + ts-node: 10.9.2(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5) + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + + jest-config@29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4)): dependencies: '@babel/core': 7.22.10 '@jest/test-sequencer': 29.7.0 @@ -42815,13 +43044,13 @@ snapshots: slash: 3.0.0 strip-json-comments: 3.1.1 optionalDependencies: - '@types/node': 20.10.0 - ts-node: 10.9.2(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5) + '@types/node': 20.14.14 + ts-node: 10.9.2(@types/node@20.14.14)(typescript@5.5.4) transitivePeerDependencies: - babel-plugin-macros - supports-color - jest-config@29.7.0(@types/node@20.12.7)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)): + jest-config@29.7.0(@types/node@22.1.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5)): dependencies: '@babel/core': 7.22.10 '@jest/test-sequencer': 29.7.0 @@ -42846,13 +43075,13 @@ snapshots: slash: 3.0.0 strip-json-comments: 3.1.1 optionalDependencies: - '@types/node': 20.12.7 - ts-node: 10.9.2(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5) + '@types/node': 22.1.0 + ts-node: 10.9.2(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5) transitivePeerDependencies: - babel-plugin-macros - supports-color - jest-config@29.7.0(@types/node@20.12.7)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5)): + jest-config@29.7.0(@types/node@22.1.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4)): dependencies: '@babel/core': 7.22.10 '@jest/test-sequencer': 29.7.0 @@ -42877,8 +43106,39 @@ snapshots: slash: 3.0.0 strip-json-comments: 3.1.1 optionalDependencies: - '@types/node': 20.12.7 - ts-node: 10.9.2(@types/node@20.12.7)(typescript@5.4.5) + '@types/node': 22.1.0 + ts-node: 10.9.2(@types/node@20.14.14)(typescript@5.5.4) + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + + jest-config@29.7.0(@types/node@22.1.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5)): + dependencies: + '@babel/core': 7.22.10 + '@jest/test-sequencer': 29.7.0 + '@jest/types': 29.6.3 + babel-jest: 29.7.0(@babel/core@7.22.10) + chalk: 4.1.2 + ci-info: 3.8.0 + deepmerge: 4.3.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-circus: 29.7.0(babel-plugin-macros@3.1.0) + jest-environment-node: 29.7.0 + jest-get-type: 29.6.3 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-runner: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + micromatch: 4.0.5 + parse-json: 5.2.0 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-json-comments: 3.1.1 + optionalDependencies: + '@types/node': 22.1.0 + ts-node: 10.9.2(@types/node@22.1.0)(typescript@5.4.5) transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -42926,7 +43186,7 @@ snapshots: '@jest/environment': 27.5.1 '@jest/fake-timers': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 20.12.7 + '@types/node': 22.1.0 jest-mock: 27.5.1 jest-util: 27.5.1 jsdom: 16.7.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) @@ -42942,7 +43202,7 @@ snapshots: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 '@types/jsdom': 20.0.1 - '@types/node': 20.12.7 + '@types/node': 20.14.14 jest-mock: 29.7.0 jest-util: 29.7.0 jsdom: 20.0.3(bufferutil@4.0.8)(utf-8-validate@6.0.3) @@ -42956,7 +43216,7 @@ snapshots: '@jest/environment': 27.5.1 '@jest/fake-timers': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 20.12.7 + '@types/node': 22.1.0 jest-mock: 27.5.1 jest-util: 27.5.1 @@ -42965,7 +43225,7 @@ snapshots: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 22.1.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -42977,7 +43237,7 @@ snapshots: dependencies: '@jest/types': 27.5.1 '@types/graceful-fs': 4.1.6 - '@types/node': 20.12.7 + '@types/node': 22.1.0 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -42994,7 +43254,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.6 - '@types/node': 20.12.7 + '@types/node': 22.1.0 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -43012,7 +43272,7 @@ snapshots: '@jest/source-map': 27.5.1 '@jest/test-result': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 20.12.7 + '@types/node': 22.1.0 chalk: 4.1.2 co: 4.6.0 expect: 27.5.1 @@ -43091,12 +43351,12 @@ snapshots: jest-mock@27.5.1: dependencies: '@jest/types': 27.5.1 - '@types/node': 20.12.7 + '@types/node': 22.1.0 jest-mock@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 20.14.14 jest-util: 29.7.0 jest-pnp-resolver@1.2.3(jest-resolve@27.5.1): @@ -43160,7 +43420,7 @@ snapshots: '@jest/test-result': 27.5.1 '@jest/transform': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 20.12.7 + '@types/node': 22.1.0 chalk: 4.1.2 emittery: 0.8.1 graceful-fs: 4.2.11 @@ -43189,7 +43449,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 22.1.0 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 @@ -43244,7 +43504,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 22.1.0 chalk: 4.1.2 cjs-module-lexer: 1.2.3 collect-v8-coverage: 1.0.2 @@ -43264,7 +43524,7 @@ snapshots: jest-serializer@27.5.1: dependencies: - '@types/node': 20.12.7 + '@types/node': 22.1.0 graceful-fs: 4.2.11 jest-snapshot@27.5.1: @@ -43322,7 +43582,7 @@ snapshots: jest-util@27.5.1: dependencies: '@jest/types': 27.5.1 - '@types/node': 20.12.7 + '@types/node': 22.1.0 chalk: 4.1.2 ci-info: 3.8.0 graceful-fs: 4.2.11 @@ -43331,7 +43591,7 @@ snapshots: jest-util@28.1.3: dependencies: '@jest/types': 28.1.3 - '@types/node': 20.12.7 + '@types/node': 22.1.0 chalk: 4.1.2 ci-info: 3.8.0 graceful-fs: 4.2.11 @@ -43340,7 +43600,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 20.14.14 chalk: 4.1.2 ci-info: 3.8.0 graceful-fs: 4.2.11 @@ -43364,11 +43624,11 @@ snapshots: leven: 3.1.0 pretty-format: 29.7.0 - jest-watch-typeahead@1.1.0(jest@27.5.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))(utf-8-validate@5.0.10)): + jest-watch-typeahead@1.1.0(jest@27.5.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5))(utf-8-validate@5.0.10)): dependencies: ansi-escapes: 4.3.2 chalk: 4.1.2 - jest: 27.5.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))(utf-8-validate@5.0.10) + jest: 27.5.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5))(utf-8-validate@5.0.10) jest-regex-util: 28.0.2 jest-watcher: 28.1.3 slash: 4.0.0 @@ -43379,7 +43639,7 @@ snapshots: dependencies: '@jest/test-result': 27.5.1 '@jest/types': 27.5.1 - '@types/node': 20.12.7 + '@types/node': 22.1.0 ansi-escapes: 4.3.2 chalk: 4.1.2 jest-util: 27.5.1 @@ -43389,7 +43649,7 @@ snapshots: dependencies: '@jest/test-result': 28.1.3 '@jest/types': 28.1.3 - '@types/node': 20.12.7 + '@types/node': 22.1.0 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.10.2 @@ -43400,7 +43660,7 @@ snapshots: dependencies: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 22.1.0 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -43409,34 +43669,34 @@ snapshots: jest-worker@26.6.2: dependencies: - '@types/node': 20.12.7 + '@types/node': 22.1.0 merge-stream: 2.0.0 supports-color: 7.2.0 jest-worker@27.5.1: dependencies: - '@types/node': 20.12.7 + '@types/node': 22.1.0 merge-stream: 2.0.0 supports-color: 8.1.1 jest-worker@28.1.3: dependencies: - '@types/node': 20.12.7 + '@types/node': 22.1.0 merge-stream: 2.0.0 supports-color: 8.1.1 jest-worker@29.7.0: dependencies: - '@types/node': 20.12.7 + '@types/node': 22.1.0 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 - jest@27.5.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))(utf-8-validate@5.0.10): + jest@27.5.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5))(utf-8-validate@5.0.10): dependencies: - '@jest/core': 27.5.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))(utf-8-validate@5.0.10) + '@jest/core': 27.5.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5))(utf-8-validate@5.0.10) import-local: 3.1.0 - jest-cli: 27.5.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))(utf-8-validate@5.0.10) + jest-cli: 27.5.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5))(utf-8-validate@5.0.10) transitivePeerDependencies: - bufferutil - canvas @@ -43444,24 +43704,36 @@ snapshots: - ts-node - utf-8-validate - jest@29.7.0(@types/node@20.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)): + jest@29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5)): + dependencies: + '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5)) + '@jest/types': 29.6.3 + import-local: 3.1.0 + jest-cli: 29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5)) + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + + jest@29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4)): dependencies: - '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)) + '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4)) '@jest/types': 29.6.3 import-local: 3.1.0 - jest-cli: 29.7.0(@types/node@20.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)) + jest-cli: 29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4)) transitivePeerDependencies: - '@types/node' - babel-plugin-macros - supports-color - ts-node - jest@29.7.0(@types/node@20.12.7)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5)): + jest@29.7.0(@types/node@22.1.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5)): dependencies: - '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5)) + '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5)) '@jest/types': 29.6.3 import-local: 3.1.0 - jest-cli: 29.7.0(@types/node@20.12.7)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5)) + jest-cli: 29.7.0(@types/node@22.1.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5)) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -45583,7 +45855,7 @@ snapshots: dependencies: path-key: 3.1.1 - npm-run-path@5.1.0: + npm-run-path@5.3.0: dependencies: path-key: 4.0.0 @@ -46435,37 +46707,45 @@ snapshots: postcss: 8.4.23 postcss-value-parser: 4.2.0 - postcss-load-config@4.0.1(postcss@8.4.23)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)): + postcss-load-config@4.0.1(postcss@8.4.23)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5)): dependencies: lilconfig: 2.1.0 yaml: 2.4.1 optionalDependencies: postcss: 8.4.23 - ts-node: 10.9.2(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5) + ts-node: 10.9.2(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5) - postcss-load-config@4.0.1(postcss@8.4.23)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5)): + postcss-load-config@4.0.1(postcss@8.4.23)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4)): dependencies: lilconfig: 2.1.0 yaml: 2.4.1 optionalDependencies: postcss: 8.4.23 - ts-node: 10.9.2(@types/node@20.12.7)(typescript@5.4.5) + ts-node: 10.9.2(@types/node@20.14.14)(typescript@5.5.4) - postcss-load-config@4.0.1(postcss@8.4.31)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5)): + postcss-load-config@4.0.1(postcss@8.4.23)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5)): + dependencies: + lilconfig: 2.1.0 + yaml: 2.4.1 + optionalDependencies: + postcss: 8.4.23 + ts-node: 10.9.2(@types/node@22.1.0)(typescript@5.4.5) + + postcss-load-config@4.0.1(postcss@8.4.31)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5)): dependencies: lilconfig: 2.1.0 yaml: 2.4.1 optionalDependencies: postcss: 8.4.31 - ts-node: 10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5) + ts-node: 10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5) - postcss-load-config@4.0.1(postcss@8.4.31)(ts-node@10.9.2(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5)): + postcss-load-config@4.0.1(postcss@8.4.31)(ts-node@10.9.2(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5)): dependencies: lilconfig: 2.1.0 yaml: 2.4.1 optionalDependencies: postcss: 8.4.31 - ts-node: 10.9.2(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5) + ts-node: 10.9.2(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5) postcss-loader@6.2.1(postcss@8.4.23)(webpack@5.91.0): dependencies: @@ -46952,7 +47232,7 @@ snapshots: '@protobufjs/pool': 1.1.0 '@protobufjs/utf8': 1.1.0 '@types/long': 4.0.2 - '@types/node': 20.12.7 + '@types/node': 22.1.0 long: 4.0.0 protobufjs@7.2.4: @@ -46967,7 +47247,7 @@ snapshots: '@protobufjs/path': 1.1.2 '@protobufjs/pool': 1.1.0 '@protobufjs/utf8': 1.1.0 - '@types/node': 20.12.7 + '@types/node': 20.14.14 long: 5.2.3 proxy-addr@2.0.7: @@ -47532,7 +47812,7 @@ snapshots: react-app-polyfill@3.0.0: dependencies: - core-js: 3.37.0 + core-js: 3.38.0 object-assign: 4.1.1 promise: 8.3.0 raf: 3.4.1 @@ -47823,7 +48103,7 @@ snapshots: react: 18.2.0 shallow-equal: 1.2.1 - react-scripts@5.0.1(@babel/plugin-syntax-flow@7.24.1(@babel/core@7.24.4))(@babel/plugin-transform-react-jsx@7.23.4(@babel/core@7.24.4))(@types/babel__core@7.20.5)(bufferutil@4.0.8)(eslint@8.57.0)(react@18.2.0)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))(type-fest@4.18.3)(typescript@5.4.5)(utf-8-validate@5.0.10)(vue-template-compiler@2.7.16): + react-scripts@5.0.1(@babel/plugin-syntax-flow@7.24.1(@babel/core@7.24.4))(@babel/plugin-transform-react-jsx@7.23.4(@babel/core@7.24.4))(@types/babel__core@7.20.5)(bufferutil@4.0.8)(eslint@8.57.0)(react@18.2.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5))(type-fest@4.18.3)(typescript@5.4.5)(utf-8-validate@5.0.10)(vue-template-compiler@2.7.16): dependencies: '@babel/core': 7.24.4 '@pmmmwh/react-refresh-webpack-plugin': 0.5.13(react-refresh@0.11.0)(type-fest@4.18.3)(webpack-dev-server@4.15.2(bufferutil@4.0.8)(utf-8-validate@5.0.10)(webpack@5.91.0))(webpack@5.91.0) @@ -47841,15 +48121,15 @@ snapshots: dotenv: 10.0.0 dotenv-expand: 5.1.0 eslint: 8.57.0 - eslint-config-react-app: 7.0.1(@babel/plugin-syntax-flow@7.24.1(@babel/core@7.24.4))(@babel/plugin-transform-react-jsx@7.23.4(@babel/core@7.24.4))(eslint@8.57.0)(jest@27.5.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))(utf-8-validate@5.0.10))(typescript@5.4.5) + eslint-config-react-app: 7.0.1(@babel/plugin-syntax-flow@7.24.1(@babel/core@7.24.4))(@babel/plugin-transform-react-jsx@7.23.4(@babel/core@7.24.4))(eslint@8.57.0)(jest@27.5.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5))(utf-8-validate@5.0.10))(typescript@5.4.5) eslint-webpack-plugin: 3.2.0(eslint@8.57.0)(webpack@5.91.0) file-loader: 6.2.0(webpack@5.91.0) fs-extra: 10.1.0 html-webpack-plugin: 5.6.0(webpack@5.91.0) identity-obj-proxy: 3.0.0 - jest: 27.5.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))(utf-8-validate@5.0.10) + jest: 27.5.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5))(utf-8-validate@5.0.10) jest-resolve: 27.5.1 - jest-watch-typeahead: 1.1.0(jest@27.5.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5))(utf-8-validate@5.0.10)) + jest-watch-typeahead: 1.1.0(jest@27.5.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5))(utf-8-validate@5.0.10)) mini-css-extract-plugin: 2.9.0(webpack@5.91.0) postcss: 8.4.23 postcss-flexbugs-fixes: 5.0.2(postcss@8.4.23) @@ -47867,7 +48147,7 @@ snapshots: semver: 7.6.0 source-map-loader: 3.0.2(webpack@5.91.0) style-loader: 3.3.3(webpack@5.91.0) - tailwindcss: 3.3.2(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5)) + tailwindcss: 3.3.2(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5)) terser-webpack-plugin: 5.3.10(webpack@5.91.0) webpack: 5.91.0 webpack-dev-server: 4.15.2(bufferutil@4.0.8)(utf-8-validate@5.0.10)(webpack@5.91.0) @@ -49146,7 +49426,7 @@ snapshots: solidity-comments-extractor@0.0.7: {} - solidity-coverage@0.8.2(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)): + solidity-coverage@0.8.2(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)): dependencies: '@ethersproject/abi': 5.7.0 '@solidity-parser/parser': 0.14.5 @@ -49158,7 +49438,7 @@ snapshots: ghost-testrpc: 0.0.2 global-modules: 2.0.0 globby: 10.0.2 - hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) + hardhat: 2.20.1(bufferutil@4.0.8)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) jsonschema: 1.4.1 lodash: 4.17.21 mocha: 7.1.2 @@ -49829,11 +50109,43 @@ snapshots: tailwind-merge@1.13.2: {} - tailwindcss-animate@1.0.7(tailwindcss@3.3.2(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))): + tailwindcss-animate@1.0.7(tailwindcss@3.3.2(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5))): + dependencies: + tailwindcss: 3.3.2(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5)) + + tailwindcss-animate@1.0.7(tailwindcss@3.3.2(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))): dependencies: - tailwindcss: 3.3.2(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)) + tailwindcss: 3.3.2(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4)) + + tailwindcss@3.3.2(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5)): + dependencies: + '@alloc/quick-lru': 5.2.0 + arg: 5.0.2 + chokidar: 3.5.3 + didyoumean: 1.2.2 + dlv: 1.1.3 + fast-glob: 3.3.1 + glob-parent: 6.0.2 + is-glob: 4.0.3 + jiti: 1.21.0 + lilconfig: 2.1.0 + micromatch: 4.0.5 + normalize-path: 3.0.0 + object-hash: 3.0.0 + picocolors: 1.0.0 + postcss: 8.4.23 + postcss-import: 15.1.0(postcss@8.4.23) + postcss-js: 4.0.1(postcss@8.4.23) + postcss-load-config: 4.0.1(postcss@8.4.23)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5)) + postcss-nested: 6.0.1(postcss@8.4.23) + postcss-selector-parser: 6.0.13 + postcss-value-parser: 4.2.0 + resolve: 1.22.8 + sucrase: 3.34.0 + transitivePeerDependencies: + - ts-node - tailwindcss@3.3.2(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)): + tailwindcss@3.3.2(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4)): dependencies: '@alloc/quick-lru': 5.2.0 arg: 5.0.2 @@ -49852,7 +50164,7 @@ snapshots: postcss: 8.4.23 postcss-import: 15.1.0(postcss@8.4.23) postcss-js: 4.0.1(postcss@8.4.23) - postcss-load-config: 4.0.1(postcss@8.4.23)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)) + postcss-load-config: 4.0.1(postcss@8.4.23)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4)) postcss-nested: 6.0.1(postcss@8.4.23) postcss-selector-parser: 6.0.13 postcss-value-parser: 4.2.0 @@ -49861,7 +50173,7 @@ snapshots: transitivePeerDependencies: - ts-node - tailwindcss@3.3.2(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5)): + tailwindcss@3.3.2(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5)): dependencies: '@alloc/quick-lru': 5.2.0 arg: 5.0.2 @@ -49880,7 +50192,7 @@ snapshots: postcss: 8.4.23 postcss-import: 15.1.0(postcss@8.4.23) postcss-js: 4.0.1(postcss@8.4.23) - postcss-load-config: 4.0.1(postcss@8.4.23)(ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5)) + postcss-load-config: 4.0.1(postcss@8.4.23)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5)) postcss-nested: 6.0.1(postcss@8.4.23) postcss-selector-parser: 6.0.13 postcss-value-parser: 4.2.0 @@ -50026,7 +50338,7 @@ snapshots: type-fest: 0.16.0 unique-string: 2.0.0 - tenderly@0.0.3(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5): + tenderly@0.0.3(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4))(typescript@5.5.4): dependencies: axios: 0.27.2(debug@4.3.4) cli-table3: 0.6.4 @@ -50037,8 +50349,8 @@ snapshots: open: 8.4.2 prompts: 2.4.2 optionalDependencies: - ts-node: 10.9.2(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5) - typescript: 5.4.5 + ts-node: 10.9.2(@types/node@20.14.14)(typescript@5.5.4) + typescript: 5.5.4 transitivePeerDependencies: - debug - supports-color @@ -50285,9 +50597,13 @@ snapshots: dependencies: typescript: 5.4.5 - ts-essentials@7.0.3(typescript@5.4.5): + ts-essentials@6.0.7(typescript@5.5.4): dependencies: - typescript: 5.4.5 + typescript: 5.5.4 + + ts-essentials@7.0.3(typescript@5.5.4): + dependencies: + typescript: 5.5.4 ts-generator@0.1.1: dependencies: @@ -50303,11 +50619,11 @@ snapshots: ts-interface-checker@0.1.13: {} - ts-jest@29.1.1(@babel/core@7.24.4)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.4))(jest@29.7.0(@types/node@20.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)))(typescript@5.4.5): + ts-jest@29.1.1(@babel/core@7.24.4)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.4))(jest@29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5)))(typescript@5.4.5): dependencies: bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@20.10.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.10.0)(typescript@5.4.5)) + jest: 29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5)) jest-util: 29.7.0 json5: 2.2.3 lodash.memoize: 4.1.2 @@ -50320,6 +50636,23 @@ snapshots: '@jest/types': 29.6.3 babel-jest: 29.7.0(@babel/core@7.24.4) + ts-jest@29.1.1(@babel/core@7.24.4)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.4))(jest@29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4)))(typescript@5.5.4): + dependencies: + bs-logger: 0.2.6 + fast-json-stable-stringify: 2.1.0 + jest: 29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4)) + jest-util: 29.7.0 + json5: 2.2.3 + lodash.memoize: 4.1.2 + make-error: 1.3.6 + semver: 7.5.4 + typescript: 5.5.4 + yargs-parser: 21.1.1 + optionalDependencies: + '@babel/core': 7.24.4 + '@jest/types': 29.6.3 + babel-jest: 29.7.0(@babel/core@7.24.4) + ts-morph@12.0.0: dependencies: '@ts-morph/common': 0.11.1 @@ -50365,14 +50698,14 @@ snapshots: optionalDependencies: '@swc/core': 1.4.2(@swc/helpers@0.5.6) - ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5): + ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.9 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 20.10.0 + '@types/node': 20.14.14 acorn: 8.10.0 acorn-walk: 8.2.0 arg: 4.1.3 @@ -50385,14 +50718,14 @@ snapshots: optionalDependencies: '@swc/core': 1.4.2(@swc/helpers@0.5.6) - ts-node@10.9.2(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5): + ts-node@10.9.2(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.9 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 20.10.0 + '@types/node': 20.14.14 acorn: 8.11.3 acorn-walk: 8.2.0 arg: 4.1.3 @@ -50405,14 +50738,33 @@ snapshots: optionalDependencies: '@swc/core': 1.4.2(@swc/helpers@0.5.6) - ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.5): + ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.9 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 20.12.7 + '@types/node': 20.14.14 + acorn: 8.11.3 + acorn-walk: 8.2.0 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 5.5.4 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + optional: true + + ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5): + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.9 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 22.1.0 acorn: 8.11.3 acorn-walk: 8.2.0 arg: 4.1.3 @@ -50460,7 +50812,7 @@ snapshots: tsort@0.0.1: {} - tsup@7.2.0(@swc/core@1.4.2)(postcss@8.4.31)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5): + tsup@7.2.0(@swc/core@1.4.2)(postcss@8.4.31)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5): dependencies: bundle-require: 4.0.1(esbuild@0.18.20) cac: 6.7.14 @@ -50470,7 +50822,7 @@ snapshots: execa: 5.1.1 globby: 11.1.0 joycon: 3.1.1 - postcss-load-config: 4.0.1(postcss@8.4.31)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5)) + postcss-load-config: 4.0.1(postcss@8.4.31)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5)) resolve-from: 5.0.0 rollup: 3.28.0 source-map: 0.8.0-beta.0 @@ -50484,7 +50836,7 @@ snapshots: - supports-color - ts-node - tsup@7.2.0(@swc/core@1.4.2)(postcss@8.4.31)(ts-node@10.9.2(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5))(typescript@5.4.5): + tsup@7.2.0(@swc/core@1.4.2)(postcss@8.4.31)(ts-node@10.9.2(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5): dependencies: bundle-require: 4.0.1(esbuild@0.18.20) cac: 6.7.14 @@ -50494,7 +50846,7 @@ snapshots: execa: 5.1.1 globby: 11.1.0 joycon: 3.1.1 - postcss-load-config: 4.0.1(postcss@8.4.31)(ts-node@10.9.2(@swc/core@1.4.2)(@types/node@20.10.0)(typescript@5.4.5)) + postcss-load-config: 4.0.1(postcss@8.4.31)(ts-node@10.9.2(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5)) resolve-from: 5.0.0 rollup: 3.28.0 source-map: 0.8.0-beta.0 @@ -50624,7 +50976,20 @@ snapshots: - supports-color - typescript - typechain@8.3.2(typescript@5.4.5): + typechain@3.0.0(typescript@5.5.4): + dependencies: + command-line-args: 4.0.7 + debug: 4.3.4(supports-color@8.1.1) + fs-extra: 7.0.1 + js-sha3: 0.8.0 + lodash: 4.17.21 + ts-essentials: 6.0.7(typescript@5.5.4) + ts-generator: 0.1.1 + transitivePeerDependencies: + - supports-color + - typescript + + typechain@8.3.2(typescript@5.5.4): dependencies: '@types/prettier': 2.7.3 debug: 4.3.4(supports-color@8.1.1) @@ -50635,8 +51000,8 @@ snapshots: mkdirp: 1.0.4 prettier: 2.8.1 ts-command-line-args: 2.5.1 - ts-essentials: 7.0.3(typescript@5.4.5) - typescript: 5.4.5 + ts-essentials: 7.0.3(typescript@5.5.4) + typescript: 5.5.4 transitivePeerDependencies: - supports-color @@ -50707,6 +51072,8 @@ snapshots: typescript@5.4.5: {} + typescript@5.5.4: {} + typewise-core@1.2.0: {} typewise@1.0.3: @@ -50756,6 +51123,8 @@ snapshots: undici-types@5.26.5: {} + undici-types@6.13.0: {} + undici@5.23.0: dependencies: busboy: 1.6.0 @@ -51252,14 +51621,14 @@ snapshots: - utf-8-validate - zod - vite-node@0.34.6(@types/node@20.12.7)(less@4.2.0)(terser@5.30.3): + vite-node@0.34.6(@types/node@22.1.0)(less@4.2.0)(terser@5.30.3): dependencies: cac: 6.7.14 debug: 4.3.4(supports-color@8.1.1) mlly: 1.4.0 pathe: 1.1.1 picocolors: 1.0.0 - vite: 4.3.9(@types/node@20.12.7)(less@4.2.0)(terser@5.30.3) + vite: 4.3.9(@types/node@22.1.0)(less@4.2.0)(terser@5.30.3) transitivePeerDependencies: - '@types/node' - less @@ -51269,13 +51638,13 @@ snapshots: - supports-color - terser - vite@4.3.9(@types/node@20.12.7)(less@4.2.0)(terser@5.30.3): + vite@4.3.9(@types/node@22.1.0)(less@4.2.0)(terser@5.30.3): dependencies: esbuild: 0.17.19 postcss: 8.4.23 rollup: 3.28.0 optionalDependencies: - '@types/node': 20.12.7 + '@types/node': 22.1.0 fsevents: 2.3.3 less: 4.2.0 terser: 5.30.3 @@ -51284,7 +51653,7 @@ snapshots: dependencies: '@types/chai': 4.3.5 '@types/chai-subset': 1.3.3 - '@types/node': 20.12.7 + '@types/node': 22.1.0 '@vitest/expect': 0.34.6 '@vitest/runner': 0.34.6 '@vitest/snapshot': 0.34.6 @@ -51303,8 +51672,8 @@ snapshots: strip-literal: 1.3.0 tinybench: 2.5.0 tinypool: 0.7.0 - vite: 4.3.9(@types/node@20.12.7)(less@4.2.0)(terser@5.30.3) - vite-node: 0.34.6(@types/node@20.12.7)(less@4.2.0)(terser@5.30.3) + vite: 4.3.9(@types/node@22.1.0)(less@4.2.0)(terser@5.30.3) + vite-node: 0.34.6(@types/node@22.1.0)(less@4.2.0)(terser@5.30.3) why-is-node-running: 2.2.2 optionalDependencies: '@edge-runtime/vm': 3.2.0 From bfa558f9bddb05a346167bba9ea1673a48ade17f Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Wed, 7 Aug 2024 18:45:10 +0100 Subject: [PATCH 085/125] fix: v2 pool test --- apps/web/test/pool/pool.test.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/web/test/pool/pool.test.ts b/apps/web/test/pool/pool.test.ts index 7c3efe2596..914a374a19 100644 --- a/apps/web/test/pool/pool.test.ts +++ b/apps/web/test/pool/pool.test.ts @@ -108,12 +108,13 @@ test.beforeEach(async ({ page, next }) => { // TEMP: Mock V2 POOL.. await page.route( - 'http://localhost:3000/pools/api/graphPool/137:0x0b65273d824393e2f43357a4096e5ebd17c89629', + 'http://localhost:3000/pools/api/graphPool/137:0x74c9bcd8a09d8b80a5654ccd6d338965f6937789', + // 'http://localhost:3000/pools/api/graphPool/137:0x0b65273d824393e2f43357a4096e5ebd17c89629', async (route) => { await route.fulfill({ json: { - id: '137:0x0b65273d824393e2f43357a4096e5ebd17c89629', - address: '0x0b65273d824393e2f43357a4096e5ebd17c89629', + id: '137:0x74c9bcd8a09d8b80a5654ccd6d338965f6937789', + address: '0x74c9bcd8a09d8b80a5654ccd6d338965f6937789', chainId: 137, name: `WMATIC-FT`, swapFee: 0.003, From 8d5340881d78639f8b52c8f22b2e58281903cb20 Mon Sep 17 00:00:00 2001 From: matthewlilley Date: Wed, 7 Aug 2024 17:46:52 +0000 Subject: [PATCH 086/125] chore: lint --- apps/web/src/lib/swap/cross-chain/actions/getTrade.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web/src/lib/swap/cross-chain/actions/getTrade.ts b/apps/web/src/lib/swap/cross-chain/actions/getTrade.ts index bf9b7af629..e5e1e41dac 100644 --- a/apps/web/src/lib/swap/cross-chain/actions/getTrade.ts +++ b/apps/web/src/lib/swap/cross-chain/actions/getTrade.ts @@ -3,8 +3,8 @@ import { // getTradeQueryApiVersion, tradeValidator02, } from '@sushiswap/react-query' -import { RouteStatus } from 'sushi/tines' import { API_BASE_URL } from 'sushi/config' +import { RouteStatus } from 'sushi/tines' import { Address } from 'viem' import { z } from 'zod' From fe28f1c55f3c6db6aaef2e402e8e4067465e60cf Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Wed, 7 Aug 2024 19:09:06 +0100 Subject: [PATCH 087/125] fix: fork block number in workflow --- .github/workflows/apps-web-e2e.yml | 2 +- apps/web/.env.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/apps-web-e2e.yml b/.github/workflows/apps-web-e2e.yml index a49ed0fa06..ec554d3046 100644 --- a/.github/workflows/apps-web-e2e.yml +++ b/.github/workflows/apps-web-e2e.yml @@ -30,7 +30,7 @@ jobs: timeout-minutes: 15 strategy: matrix: - block-number: [60301962] + block-number: [60306923] chain-id: [137] node-version: [20] pnpm-version: [9.4.0] diff --git a/apps/web/.env.test b/apps/web/.env.test index b5f3d6095a..6d83653f35 100644 --- a/apps/web/.env.test +++ b/apps/web/.env.test @@ -1,4 +1,4 @@ -ANVIL_BLOCK_NUMBER=60301962 +ANVIL_BLOCK_NUMBER=60306923 ANVIL_FORK_URL=https://polygon-mainnet.g.alchemy.com/v2/ ANVIL_PORT=8545 EDGE_CONFIG= From 4105eb3f138c77a9cb157c9281139cb89ba51654 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Wed, 7 Aug 2024 19:17:49 +0100 Subject: [PATCH 088/125] chore: function for consistency --- apis/router/src/handlers/swap2/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apis/router/src/handlers/swap2/index.ts b/apis/router/src/handlers/swap2/index.ts index 6b144f4368..befba9fb72 100644 --- a/apis/router/src/handlers/swap2/index.ts +++ b/apis/router/src/handlers/swap2/index.ts @@ -48,11 +48,11 @@ async function processUnknownToken( return token } -const handler = ( +function handler( querySchema: typeof querySchema5, routeProcessorParams: typeof Router.routeProcessor5Params, routeProcessorAddress: Address, -) => { +) { return (client: ExtractorClient) => { return async (req: Request, res: Response) => { res.setHeader('Cache-Control', 's-maxage=2, stale-while-revalidate=28') From 3e53cee3ab1154d08fe7b9c1d4f4ca0c17824b92 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Wed, 7 Aug 2024 19:18:09 +0100 Subject: [PATCH 089/125] chore: remove framer for swap buttons --- apps/web/src/ui/swap/swap-mode-buttons.tsx | 25 +++++++++------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/apps/web/src/ui/swap/swap-mode-buttons.tsx b/apps/web/src/ui/swap/swap-mode-buttons.tsx index 982befb18a..34142aa79c 100644 --- a/apps/web/src/ui/swap/swap-mode-buttons.tsx +++ b/apps/web/src/ui/swap/swap-mode-buttons.tsx @@ -10,7 +10,6 @@ import { HoverCardTrigger, } from '@sushiswap/ui' import { ShuffleIcon } from '@sushiswap/ui/icons/ShuffleIcon' -import { motion } from 'framer-motion' import Link from 'next/link' import { PathnameButton } from '../pathname-button' @@ -24,20 +23,16 @@ export const SwapModeButtons = () => { - - - - - - - - Cross Chain - - - - - - + + + + + + Cross Chain + + + + Cross-chain Swap From 296653cf720b9881dbd465da75ebd7798c2473ea Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Wed, 7 Aug 2024 19:18:37 +0100 Subject: [PATCH 090/125] chore: remove unused route --- apps/web/src/app/(evm)/swap/advanced/layout.tsx | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 apps/web/src/app/(evm)/swap/advanced/layout.tsx diff --git a/apps/web/src/app/(evm)/swap/advanced/layout.tsx b/apps/web/src/app/(evm)/swap/advanced/layout.tsx deleted file mode 100644 index 60c025167a..0000000000 --- a/apps/web/src/app/(evm)/swap/advanced/layout.tsx +++ /dev/null @@ -1,9 +0,0 @@ -export const metadata = { - title: 'SushiSwap Avanced', -} - -export default function SwapAdvancedLayout({ - children, -}: { children: React.ReactNode }) { - return { children } -} From b3a4e1f8ee46c33bc3cdaeeba066ba95a1f163ce Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Wed, 7 Aug 2024 20:04:02 +0100 Subject: [PATCH 091/125] fix: test --- apps/web/test/playwright.config.ts | 4 ++-- apps/web/test/swap/scripts/generate-swaps.ts | 24 +++++++++----------- apps/web/test/swap/simple.test.ts | 14 +++--------- 3 files changed, 16 insertions(+), 26 deletions(-) diff --git a/apps/web/test/playwright.config.ts b/apps/web/test/playwright.config.ts index 47462d8db6..d559fc4aee 100644 --- a/apps/web/test/playwright.config.ts +++ b/apps/web/test/playwright.config.ts @@ -21,8 +21,8 @@ const config: PlaywrightTestConfig = { // quiet: !!process.env.CI, quiet: true, testMatch: [ - 'pool.test.ts', 'simple.test.ts', + 'pool.test.ts', // 'smart.test.ts', // 'cross-chain.test.ts', ], @@ -136,7 +136,7 @@ const config: PlaywrightTestConfig = { reuseExistingServer: !process.env.CI, env: { EDGE_CONFIG: String(process.env.EDGE_CONFIG), - NEXT_PUBLIC_APP_ENV: String(process.env.NEXT_PUBLIC_APP_ENV), + NEXT_PUBLIC_APP_ENV: 'test', NEXT_PUBLIC_CHAIN_ID: String(process.env.NEXT_PUBLIC_CHAIN_ID), }, // stderr: 'pipe', diff --git a/apps/web/test/swap/scripts/generate-swaps.ts b/apps/web/test/swap/scripts/generate-swaps.ts index 57b320a66f..70fcf5be6a 100644 --- a/apps/web/test/swap/scripts/generate-swaps.ts +++ b/apps/web/test/swap/scripts/generate-swaps.ts @@ -3,8 +3,8 @@ import { type UseTradeParams, tradeValidator02 } from '@sushiswap/react-query' import { ChainId } from 'sushi/chain' import { API_BASE_URL, - MULTISIG_ADDRESS, - isMultisigChainId, + // MULTISIG_ADDRESS, + // isMultisigChainId, publicClientConfig, } from 'sushi/config' import { Amount, Native, USDC, USDT, WBTC } from 'sushi/currency' @@ -83,22 +83,20 @@ const getSwapApiResult = async ({ params.searchParams.set('gasPrice', `${gasPrice}`) params.searchParams.set('to', `${RECIPIENT}`) params.searchParams.set('preferSushi', 'true') - params.searchParams.set('enableFee', 'true') - params.searchParams.set( - 'feeReceiver', - isMultisigChainId(chainId) - ? MULTISIG_ADDRESS[chainId] - : '0xFF64C2d5e23e9c48e8b42a23dc70055EEC9ea098', - ) - params.searchParams.set('fee', '0.0025') - params.searchParams.set('feeBy', 'output') + // params.searchParams.set('enableFee', 'true') + // params.searchParams.set( + // 'feeReceiver', + // isMultisigChainId(chainId) + // ? MULTISIG_ADDRESS[chainId] + // : '0xFF64C2d5e23e9c48e8b42a23dc70055EEC9ea098', + // ) + // params.searchParams.set('fee', '0.0025') + // params.searchParams.set('feeBy', 'output') params.searchParams.set('includeTransaction', 'true') params.searchParams.set('includeRoute', 'true') if (source !== undefined) params.searchParams.set('source', `${source}`) - console.log(params.toString()) - const res = await fetch(params.toString()) const json = await res.json() const resp = tradeValidator02.parse(json) diff --git a/apps/web/test/swap/simple.test.ts b/apps/web/test/swap/simple.test.ts index bf36690828..58f52e310f 100644 --- a/apps/web/test/swap/simple.test.ts +++ b/apps/web/test/swap/simple.test.ts @@ -22,15 +22,7 @@ const url = 'http://localhost:3000/swap' const native = Native.onChain(chainId) const wnative = native.wrapped -const polygonBridgedUsdc = new Token({ - chainId: ChainId.POLYGON, - address: '0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174', - symbol: 'USDC.e', - name: 'USD Coin (PoS)', - decimals: 6, -}) - -const usdc = chainId === ChainId.POLYGON ? polygonBridgedUsdc : USDC[chainId] +const usdc = USDC[chainId] const usdt = USDT[chainId] const wbtc = WBTC[chainId] // let snapshot: string @@ -87,10 +79,10 @@ test('Wrap and unwrap', async ({ page }) => { await swapPage.connect() await swapPage.switchNetwork(chainId) await swapPage.mockSwapApi(`test/swap/mock/${chainId}-wrap.json`) - await swapPage.wrap(native, wnative, '10') + await swapPage.wrap(native, wnative, '100') await swapPage.mockSwapApi(`test/swap/mock/${chainId}-unwrap.json`) - await swapPage.wrap(wnative, native, '10') + await swapPage.wrap(wnative, native, '100') }) test('swap Native to USDC, then USDC to NATIVE', async ({ page }) => { From 81ff35ef541e00018c457d0ebe9e401088cabe5a Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Wed, 7 Aug 2024 20:05:32 +0100 Subject: [PATCH 092/125] chore: lint --- apps/web/test/swap/simple.test.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/web/test/swap/simple.test.ts b/apps/web/test/swap/simple.test.ts index 58f52e310f..366bc90919 100644 --- a/apps/web/test/swap/simple.test.ts +++ b/apps/web/test/swap/simple.test.ts @@ -1,6 +1,5 @@ import { test } from 'next/experimental/testmode/playwright.js' -import { ChainId } from 'sushi/chain' -import { Native, Token, USDC, USDT, WBTC } from 'sushi/currency' +import { Native, USDC, USDT, WBTC } from 'sushi/currency' import { SwapPage } from 'test/helpers/swap' import { // createSnapshot, From 561339bc43c8ddd6244d93e499148ab26a407270 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Wed, 7 Aug 2024 20:15:53 +0100 Subject: [PATCH 093/125] chore: extract chain id and native amount --- apps/web/test/constants.ts | 21 +++++++++++++++++++++ apps/web/test/playwright.config.ts | 2 +- apps/web/test/pool/pool.test.ts | 28 ++++++++++++---------------- apps/web/test/swap/simple.test.ts | 22 +++++++--------------- 4 files changed, 41 insertions(+), 32 deletions(-) diff --git a/apps/web/test/constants.ts b/apps/web/test/constants.ts index 1cde2b55a3..36d999415b 100644 --- a/apps/web/test/constants.ts +++ b/apps/web/test/constants.ts @@ -1,3 +1,6 @@ +import { ChainId } from 'sushi' +import { Amount, Native } from 'sushi/currency' + export let forkBlockNumber: bigint if (process.env.ANVIL_BLOCK_NUMBER) { forkBlockNumber = BigInt(Number(process.env.ANVIL_BLOCK_NUMBER)) @@ -34,8 +37,26 @@ if (process.env.ANVIL_PORT) { // console.warn(`\`ANVIL_PORT\` not found. Falling back to \`${anvilPort}\`.`) } +export let chainId: typeof ChainId.ETHEREUM | typeof ChainId.POLYGON +if (process.env.NEXT_PUBLIC_CHAIN_ID) { + chainId = Number(process.env.NEXT_PUBLIC_CHAIN_ID) +} else { + chainId = 137 + // console.warn(`\`ANVIL_PORT\` not found. Falling back to \`${anvilPort}\`.`) +} + export const testWorkerIndex = Number(process.env.TEST_WORKER_INDEX ?? 0) export const testParallelIndex = Number(process.env.TEST_PARALLEL_INDEX ?? 0) export const localHttpUrl = `http://127.0.0.1:${anvilPort}/${testParallelIndex}` export const localWsUrl = `ws://127.0.0.1:${anvilPort}/${testParallelIndex}` + +// Assume 100MATIC for Polygon, 1PROBABLY_ETH for the rest +export const nativeAmounts: Partial>> = { + [ChainId.POLYGON]: Amount.fromRawAmount( + Native.onChain(ChainId.POLYGON), + 1e20, + ), +} +export const nativeAmount = + nativeAmounts[chainId] || Amount.fromRawAmount(Native.onChain(chainId), 1e18) diff --git a/apps/web/test/playwright.config.ts b/apps/web/test/playwright.config.ts index d559fc4aee..fefc094492 100644 --- a/apps/web/test/playwright.config.ts +++ b/apps/web/test/playwright.config.ts @@ -22,7 +22,7 @@ const config: PlaywrightTestConfig = { quiet: true, testMatch: [ 'simple.test.ts', - 'pool.test.ts', + // 'pool.test.ts', // 'smart.test.ts', // 'cross-chain.test.ts', ], diff --git a/apps/web/test/pool/pool.test.ts b/apps/web/test/pool/pool.test.ts index 914a374a19..b96640a172 100644 --- a/apps/web/test/pool/pool.test.ts +++ b/apps/web/test/pool/pool.test.ts @@ -6,16 +6,12 @@ import { } from 'sushi/config' import { Native, Token } from 'sushi/currency' import { Fee } from 'sushi/dex' +import { chainId } from 'test/constants' import { createERC20 } from 'test/erc20' import { PoolPage } from 'test/helpers/pool' import { interceptAnvil } from 'test/intercept-anvil' -if (typeof process.env.NEXT_PUBLIC_CHAIN_ID !== 'string') { - new Error('NEXT_PUBLIC_CHAIN_ID not set') -} - -const CHAIN_ID = Number(process.env.NEXT_PUBLIC_CHAIN_ID as string) as 137 -const NATIVE_TOKEN = Native.onChain(CHAIN_ID) +const NATIVE_TOKEN = Native.onChain(chainId) let FAKE_TOKEN: Token @@ -35,7 +31,7 @@ test.beforeAll(async () => { try { FAKE_TOKEN = await createERC20({ - chainId: CHAIN_ID, + chainId, name: 'FakeToken', symbol: 'FT', decimals: 18, @@ -68,7 +64,7 @@ test.beforeAll(async () => { console.error( 'error creating fake token', { - chainId: CHAIN_ID, + chainId, name: 'FakeToken', symbol: 'FT', decimals: 18, @@ -170,14 +166,14 @@ test.beforeEach(async ({ page, next }) => { // Tests will only work for polygon atm test.describe('V3', () => { - test.skip(!isSushiSwapV3ChainId(CHAIN_ID)) + test.skip(!isSushiSwapV3ChainId(chainId)) test('Create, add both sides, single side each token & remove', async ({ page, next, }) => { test.slow() - const url = BASE_URL.concat('/add').concat(`?chainId=${CHAIN_ID}`) - const poolPage = new PoolPage(page, CHAIN_ID) + const url = BASE_URL.concat('/add').concat(`?chainId=${chainId}`) + const poolPage = new PoolPage(page, chainId) await poolPage.mockPoolApi( next, @@ -189,7 +185,7 @@ test.describe('V3', () => { await poolPage.goTo(url) await poolPage.connect() - await poolPage.switchNetwork(CHAIN_ID) + await poolPage.switchNetwork(chainId) await poolPage.createV3Pool({ token0: NATIVE_TOKEN, @@ -215,16 +211,16 @@ test.describe('V3', () => { }) test.describe('V2', () => { - test.skip(!isSushiSwapV2ChainId(CHAIN_ID)) + test.skip(!isSushiSwapV2ChainId(chainId)) test('Create, add & remove', async ({ page, next }) => { test.slow() - const poolPage = new PoolPage(page, CHAIN_ID) + const poolPage = new PoolPage(page, chainId) - const url = BASE_URL.concat(`/add/v2/${CHAIN_ID}`) + const url = BASE_URL.concat(`/add/v2/${chainId}`) await poolPage.goTo(url) await poolPage.connect() - await poolPage.switchNetwork(CHAIN_ID) + await poolPage.switchNetwork(chainId) await poolPage.mockPoolApi( next, diff --git a/apps/web/test/swap/simple.test.ts b/apps/web/test/swap/simple.test.ts index 366bc90919..3598fe2955 100644 --- a/apps/web/test/swap/simple.test.ts +++ b/apps/web/test/swap/simple.test.ts @@ -1,5 +1,6 @@ import { test } from 'next/experimental/testmode/playwright.js' import { Native, USDC, USDT, WBTC } from 'sushi/currency' +import { chainId, nativeAmount } from 'test/constants' import { SwapPage } from 'test/helpers/swap' import { // createSnapshot, @@ -7,15 +8,6 @@ import { // loadSnapshot, } from 'test/intercept-anvil' -if ( - typeof process.env.NEXT_PUBLIC_CHAIN_ID !== 'string' || - !process.env.NEXT_PUBLIC_CHAIN_ID -) { - throw new Error('NEXT_PUBLIC_CHAIN_ID not set') -} - -const chainId = parseInt(process.env.NEXT_PUBLIC_CHAIN_ID) as 137 - const url = 'http://localhost:3000/swap' const native = Native.onChain(chainId) @@ -78,10 +70,10 @@ test('Wrap and unwrap', async ({ page }) => { await swapPage.connect() await swapPage.switchNetwork(chainId) await swapPage.mockSwapApi(`test/swap/mock/${chainId}-wrap.json`) - await swapPage.wrap(native, wnative, '100') + await swapPage.wrap(native, wnative, nativeAmount.toExact()) await swapPage.mockSwapApi(`test/swap/mock/${chainId}-unwrap.json`) - await swapPage.wrap(wnative, native, '100') + await swapPage.wrap(wnative, native, nativeAmount.toExact()) }) test('swap Native to USDC, then USDC to NATIVE', async ({ page }) => { @@ -91,7 +83,7 @@ test('swap Native to USDC, then USDC to NATIVE', async ({ page }) => { await swapPage.connect() await swapPage.switchNetwork(chainId) await swapPage.mockSwapApi(`test/swap/mock/${chainId}-native-to-usdc.json`) - await swapPage.swap(native, usdc, '100') + await swapPage.swap(native, usdc, nativeAmount.toExact()) await swapPage.mockSwapApi(`test/swap/mock/${chainId}-usdc-to-native.json`) await swapPage.maxSwap(usdc, native) @@ -104,7 +96,7 @@ test('swap Native to USDT, then USDT to NATIVE', async ({ page }) => { await swapPage.connect() await swapPage.switchNetwork(chainId) await swapPage.mockSwapApi(`test/swap/mock/${chainId}-native-to-usdt.json`) - await swapPage.swap(native, usdt, '100') + await swapPage.swap(native, usdt, nativeAmount.toExact()) await swapPage.mockSwapApi(`test/swap/mock/${chainId}-usdt-to-native.json`) await swapPage.maxSwap(usdt, native) @@ -119,7 +111,7 @@ test('Swap Native to USDC, USDC to USDT then USDT to NATIVE', async ({ await swapPage.connect() await swapPage.switchNetwork(chainId) await swapPage.mockSwapApi(`test/swap/mock/${chainId}-native-to-usdc.json`) - await swapPage.swap(native, usdc, '100') + await swapPage.swap(native, usdc, nativeAmount.toExact()) await swapPage.mockSwapApi(`test/swap/mock/${chainId}-usdc-to-usdt.json`) await swapPage.maxSwap(usdc, usdt) @@ -136,5 +128,5 @@ test('Swap Native to WBTC', async ({ page }) => { await swapPage.switchNetwork(chainId) await swapPage.mockSwapApi(`test/swap/mock/${chainId}-native-to-wbtc.json`) - await swapPage.swap(native, wbtc, '7000') + await swapPage.swap(native, wbtc, nativeAmount.toExact()) }) From 37646a9d9ed30989f1ec9776e15fbea9ac23c85c Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Wed, 7 Aug 2024 20:23:09 +0100 Subject: [PATCH 094/125] chore: tsc errors --- apps/web/test/constants.ts | 4 ++-- apps/web/test/playwright.config.ts | 5 ++--- apps/web/test/pool/pool.test.ts | 6 +----- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/apps/web/test/constants.ts b/apps/web/test/constants.ts index 36d999415b..ce2b7f46a3 100644 --- a/apps/web/test/constants.ts +++ b/apps/web/test/constants.ts @@ -37,9 +37,9 @@ if (process.env.ANVIL_PORT) { // console.warn(`\`ANVIL_PORT\` not found. Falling back to \`${anvilPort}\`.`) } -export let chainId: typeof ChainId.ETHEREUM | typeof ChainId.POLYGON +export let chainId: typeof ChainId.POLYGON if (process.env.NEXT_PUBLIC_CHAIN_ID) { - chainId = Number(process.env.NEXT_PUBLIC_CHAIN_ID) + chainId = Number(process.env.NEXT_PUBLIC_CHAIN_ID) as typeof ChainId.POLYGON } else { chainId = 137 // console.warn(`\`ANVIL_PORT\` not found. Falling back to \`${anvilPort}\`.`) diff --git a/apps/web/test/playwright.config.ts b/apps/web/test/playwright.config.ts index fefc094492..f0559b5c95 100644 --- a/apps/web/test/playwright.config.ts +++ b/apps/web/test/playwright.config.ts @@ -18,11 +18,10 @@ const baseURL = `http://localhost:${PORT}` * See https://playwright.dev/docs/test-configuration. */ const config: PlaywrightTestConfig = { - // quiet: !!process.env.CI, - quiet: true, + quiet: !!process.env.CI, testMatch: [ 'simple.test.ts', - // 'pool.test.ts', + 'pool.test.ts', // 'smart.test.ts', // 'cross-chain.test.ts', ], diff --git a/apps/web/test/pool/pool.test.ts b/apps/web/test/pool/pool.test.ts index b96640a172..341cdea61e 100644 --- a/apps/web/test/pool/pool.test.ts +++ b/apps/web/test/pool/pool.test.ts @@ -19,11 +19,7 @@ let FAKE_TOKEN: Token // let MOCK_TOKEN_6_DP: Token // let MOCK_TOKEN_8_DP: Token // let MOCK_TOKEN_18_DP: Token -// const EVM_APP_BASE_URL = -// process.env['NEXT_PUBLIC_EVM_APP_BASE_URL'] || -// (process.env['NEXT_PUBLIC_VERCEL_URL'] -// ? `https://${process.env['NEXT_PUBLIC_VERCEL_URL']}` -// : 'http://localhost:3000') + const BASE_URL = 'http://localhost:3000/pool' test.beforeAll(async () => { From 9c25bdd945561af971245837389e3f53adc875b8 Mon Sep 17 00:00:00 2001 From: LufyCZ Date: Wed, 7 Aug 2024 21:27:02 +0000 Subject: [PATCH 095/125] refactor: move master/minichef addresses to sushi pkg --- .../master-chef/use-master-chef-contract.ts | 38 +++---------------- .../hooks/master-chef/use-master-chef.ts | 12 +++--- apps/web/src/ui/stake/VotingPowerProvider.tsx | 2 +- .../src/lib/chefs/masterChefV1/fetchers.ts | 2 +- jobs/pool/src/lib/chefs/masterChefV1/index.ts | 2 +- packages/sushi/src/config/index.ts | 1 + packages/sushi/src/config/master-chef.ts | 13 +++++++ packages/sushi/src/config/mini-chef.ts | 20 ++++++++++ 8 files changed, 48 insertions(+), 42 deletions(-) create mode 100644 packages/sushi/src/config/master-chef.ts diff --git a/apps/web/src/lib/wagmi/hooks/master-chef/use-master-chef-contract.ts b/apps/web/src/lib/wagmi/hooks/master-chef/use-master-chef-contract.ts index 0c3ac42e5f..7a8422281b 100644 --- a/apps/web/src/lib/wagmi/hooks/master-chef/use-master-chef-contract.ts +++ b/apps/web/src/lib/wagmi/hooks/master-chef/use-master-chef-contract.ts @@ -4,41 +4,13 @@ import { ChefType } from '@sushiswap/client' import { useMemo } from 'react' import { masterChefV1Abi, masterChefV2Abi, miniChefAbi } from 'sushi/abi' import { ChainId } from 'sushi/chain' +import { + MASTERCHEF_ADDRESS, + MASTERCHEF_V2_ADDRESS, + MINICHEF_ADDRESS, +} from 'sushi/config' import { Address } from 'viem' -// TODO move to package -export const MASTERCHEF_ADDRESS = { - [ChainId.ETHEREUM]: '0xc2EdaD668740f1aA35E4D8f227fB8E17dcA888Cd', - // [ChainId.ROPSTEN]: '0x80C7DD17B01855a6D2347444a0FCC36136a314de', - // [ChainId.RINKEBY]: '0x80C7DD17B01855a6D2347444a0FCC36136a314de', - // [ChainId.GÖRLI]: '0x80C7DD17B01855a6D2347444a0FCC36136a314de', - // [ChainId.KOVAN]: '0x80C7DD17B01855a6D2347444a0FCC36136a314de', -} as const - -export const MASTERCHEF_V2_ADDRESS = { - [ChainId.ETHEREUM]: '0xEF0881eC094552b2e128Cf945EF17a6752B4Ec5d', -} as const - -export const MINICHEF_ADDRESS = { - [ChainId.POLYGON]: '0x0769fd68dFb93167989C6f7254cd0D766Fb2841F', - [ChainId.GNOSIS]: '0xdDCbf776dF3dE60163066A5ddDF2277cB445E0F3', - [ChainId.HARMONY]: '0x67dA5f2FfaDDfF067AB9d5F025F8810634d84287', - [ChainId.ARBITRUM]: '0xF4d73326C13a4Fc5FD7A064217e12780e9Bd62c3', - [ChainId.CELO]: '0x8084936982D089130e001b470eDf58faCA445008', - [ChainId.MOONRIVER]: '0x3dB01570D97631f69bbb0ba39796865456Cf89A5', - [ChainId.FUSE]: '0x182CD0C6F1FaEc0aED2eA83cd0e160c8Bd4cb063', - [ChainId.FANTOM]: '0xf731202A3cf7EfA9368C2d7bD613926f7A144dB5', - [ChainId.MOONBEAM]: '0x011E52E4E40CF9498c79273329E8827b21E2e581', - [ChainId.KAVA]: '0xf731202A3cf7EfA9368C2d7bD613926f7A144dB5', - [ChainId.METIS]: '0x1334c8e873E1cae8467156e2A81d1C8b566B2da1', - [ChainId.BOBA]: '0x75f52766A6a23F736edEfCD69dfBE6153a48c3F3', - [ChainId.ARBITRUM_NOVA]: '0xC09756432dAD2FF50B2D40618f7B04546DD20043', - [ChainId.BTTC]: '0xC09756432dAD2FF50B2D40618f7B04546DD20043', - [ChainId.OPTIMISM]: '0xB25157bF349295a7Cd31D1751973f426182070D6', - [ChainId.AVALANCHE]: '0xe11252176CEDd4a493Aec9767192C06A04A6B04F', - [ChainId.BSC]: '0x5219C5E32b9FFf87F29d5A833832c29134464aaa', -} as const - export const _getMasterChefContractConfig = ( chainId: keyof typeof MASTERCHEF_ADDRESS, ) => diff --git a/apps/web/src/lib/wagmi/hooks/master-chef/use-master-chef.ts b/apps/web/src/lib/wagmi/hooks/master-chef/use-master-chef.ts index 01a66f6596..64ab0afb86 100644 --- a/apps/web/src/lib/wagmi/hooks/master-chef/use-master-chef.ts +++ b/apps/web/src/lib/wagmi/hooks/master-chef/use-master-chef.ts @@ -6,6 +6,11 @@ import { keepPreviousData, useQueryClient } from '@tanstack/react-query' import { useCallback, useEffect, useMemo } from 'react' import { erc20Abi, masterChefV2Abi, miniChefV2Abi } from 'sushi/abi' import { ChainId } from 'sushi/chain' +import { + MASTERCHEF_ADDRESS, + MASTERCHEF_V2_ADDRESS, + MINICHEF_ADDRESS, +} from 'sushi/config' import { SUSHI, SUSHI_ADDRESS } from 'sushi/currency' import { Amount, Token } from 'sushi/currency' import { Address, UserRejectedRequestError, encodeFunctionData } from 'viem' @@ -18,12 +23,7 @@ import { } from 'wagmi' import { SendTransactionErrorType } from 'wagmi/actions' import { SendTransactionData } from 'wagmi/query' -import { - MASTERCHEF_ADDRESS, - MASTERCHEF_V2_ADDRESS, - MINICHEF_ADDRESS, - useMasterChefContract, -} from './use-master-chef-contract' +import { useMasterChefContract } from './use-master-chef-contract' interface UseMasterChefReturn extends Pick, 'isLoading' | 'isError'> { diff --git a/apps/web/src/ui/stake/VotingPowerProvider.tsx b/apps/web/src/ui/stake/VotingPowerProvider.tsx index 6f00432ec5..e26011c80d 100644 --- a/apps/web/src/ui/stake/VotingPowerProvider.tsx +++ b/apps/web/src/ui/stake/VotingPowerProvider.tsx @@ -3,9 +3,9 @@ import { useQuery } from '@tanstack/react-query' import { FC, ReactNode, createContext, useContext, useMemo } from 'react' import { useBalancesWeb3 } from 'src/lib/wagmi/hooks/balances/useBalancesWeb3' -import { MASTERCHEF_ADDRESS } from 'src/lib/wagmi/hooks/master-chef/use-master-chef-contract' import { erc20Abi, masterChefV1Abi } from 'sushi/abi' import { ChainId } from 'sushi/chain' +import { MASTERCHEF_ADDRESS } from 'sushi/config' import { Amount, SUSHI_ADDRESS, diff --git a/jobs/pool/src/lib/chefs/masterChefV1/fetchers.ts b/jobs/pool/src/lib/chefs/masterChefV1/fetchers.ts index 5af0a989ad..84006a4dc2 100644 --- a/jobs/pool/src/lib/chefs/masterChefV1/fetchers.ts +++ b/jobs/pool/src/lib/chefs/masterChefV1/fetchers.ts @@ -3,7 +3,7 @@ import { masterChefV1Abi } from 'sushi/abi' import { ChainId } from 'sushi/chain' import { config } from 'src/lib/wagmi.js' -import { MASTERCHEF_ADDRESS } from '../../../config.js' +import { MASTERCHEF_ADDRESS } from 'sushi/config' export async function getPoolLength() { const poolLengthCall = { diff --git a/jobs/pool/src/lib/chefs/masterChefV1/index.ts b/jobs/pool/src/lib/chefs/masterChefV1/index.ts index 6d236f6116..6b9b7dec02 100644 --- a/jobs/pool/src/lib/chefs/masterChefV1/index.ts +++ b/jobs/pool/src/lib/chefs/masterChefV1/index.ts @@ -2,8 +2,8 @@ import { daysInYear, secondsInDay } from 'date-fns/constants' import { ChainId } from 'sushi/chain' import { SUSHI } from 'sushi/currency' +import { MASTERCHEF_ADDRESS } from 'sushi/config' import { SECONDS_BETWEEN_BLOCKS } from 'sushi/config/subgraph' -import { MASTERCHEF_ADDRESS } from '../../../config.js' import { getPairs, getTokenBalancesOf, getTokens } from '../../common/index.js' import type { ChefReturn, Farm } from '../../types.js' import { getPoolInfos, getPoolLength, getTotalAllocPoint } from './fetchers.js' diff --git a/packages/sushi/src/config/index.ts b/packages/sushi/src/config/index.ts index 506948bf01..5d58c289b3 100644 --- a/packages/sushi/src/config/index.ts +++ b/packages/sushi/src/config/index.ts @@ -7,6 +7,7 @@ export * from './default-quote.js' export * from './furo.js' export * from './default-slippage.js' export * from './lsds.js' +export * from './master-chef.js' export * from './mini-chef.js' export * from './native-ids.js' export * from './extractor.js' diff --git a/packages/sushi/src/config/master-chef.ts b/packages/sushi/src/config/master-chef.ts new file mode 100644 index 0000000000..2de4961c4a --- /dev/null +++ b/packages/sushi/src/config/master-chef.ts @@ -0,0 +1,13 @@ +import { ChainId } from '../chain/index.js' + +export const MASTERCHEF_ADDRESS = { + [ChainId.ETHEREUM]: '0xc2EdaD668740f1aA35E4D8f227fB8E17dcA888Cd', + // [ChainId.ROPSTEN]: '0x80C7DD17B01855a6D2347444a0FCC36136a314de', + // [ChainId.RINKEBY]: '0x80C7DD17B01855a6D2347444a0FCC36136a314de', + // [ChainId.GÖRLI]: '0x80C7DD17B01855a6D2347444a0FCC36136a314de', + // [ChainId.KOVAN]: '0x80C7DD17B01855a6D2347444a0FCC36136a314de', +} as const + +export const MASTERCHEF_V2_ADDRESS = { + [ChainId.ETHEREUM]: '0xEF0881eC094552b2e128Cf945EF17a6752B4Ec5d', +} as const diff --git a/packages/sushi/src/config/mini-chef.ts b/packages/sushi/src/config/mini-chef.ts index 42d6c98ce5..66e7784dd1 100644 --- a/packages/sushi/src/config/mini-chef.ts +++ b/packages/sushi/src/config/mini-chef.ts @@ -1,5 +1,25 @@ import { ChainId } from '../chain/index.js' +export const MINICHEF_ADDRESS = { + [ChainId.POLYGON]: '0x0769fd68dFb93167989C6f7254cd0D766Fb2841F', + [ChainId.GNOSIS]: '0xdDCbf776dF3dE60163066A5ddDF2277cB445E0F3', + [ChainId.HARMONY]: '0x67dA5f2FfaDDfF067AB9d5F025F8810634d84287', + [ChainId.ARBITRUM]: '0xF4d73326C13a4Fc5FD7A064217e12780e9Bd62c3', + [ChainId.CELO]: '0x8084936982D089130e001b470eDf58faCA445008', + [ChainId.MOONRIVER]: '0x3dB01570D97631f69bbb0ba39796865456Cf89A5', + [ChainId.FUSE]: '0x182CD0C6F1FaEc0aED2eA83cd0e160c8Bd4cb063', + [ChainId.FANTOM]: '0xf731202A3cf7EfA9368C2d7bD613926f7A144dB5', + [ChainId.MOONBEAM]: '0x011E52E4E40CF9498c79273329E8827b21E2e581', + [ChainId.KAVA]: '0xf731202A3cf7EfA9368C2d7bD613926f7A144dB5', + [ChainId.METIS]: '0x1334c8e873E1cae8467156e2A81d1C8b566B2da1', + [ChainId.BOBA]: '0x75f52766A6a23F736edEfCD69dfBE6153a48c3F3', + [ChainId.ARBITRUM_NOVA]: '0xC09756432dAD2FF50B2D40618f7B04546DD20043', + [ChainId.BTTC]: '0xC09756432dAD2FF50B2D40618f7B04546DD20043', + [ChainId.OPTIMISM]: '0xB25157bF349295a7Cd31D1751973f426182070D6', + [ChainId.AVALANCHE]: '0xe11252176CEDd4a493Aec9767192C06A04A6B04F', + [ChainId.BSC]: '0x5219C5E32b9FFf87F29d5A833832c29134464aaa', +} as const + export const MINICHEF_SUPPORTED_CHAIN_IDS = [ ChainId.POLYGON, ChainId.GNOSIS, From 8b4526daae1eb029cf7e1be8cf9c73600c9f8ad8 Mon Sep 17 00:00:00 2001 From: 0xMasayoshi <0xMasayoshi@protonmail.com> Date: Thu, 8 Aug 2024 09:10:21 +0700 Subject: [PATCH 096/125] chore: add RP5 cronos deployment files --- packages/sushi/src/config/route-processor.ts | 1 + .../deployments/cronos/RouteProcessor5.json | 704 ++++++++++++++++++ .../9252879aaeb02fabe759ce8768addec4.json | 98 +++ 3 files changed, 803 insertions(+) create mode 100644 protocols/route-processor/deployments/cronos/RouteProcessor5.json create mode 100644 protocols/route-processor/deployments/cronos/solcInputs/9252879aaeb02fabe759ce8768addec4.json diff --git a/packages/sushi/src/config/route-processor.ts b/packages/sushi/src/config/route-processor.ts index 115730950a..47cc29408e 100644 --- a/packages/sushi/src/config/route-processor.ts +++ b/packages/sushi/src/config/route-processor.ts @@ -378,6 +378,7 @@ export const ROUTE_PROCESSOR_5_SUPPORTED_CHAIN_IDS = [ ChainId.BLAST, ChainId.SKALE_EUROPA, ChainId.ROOTSTOCK, + ChainId.CRONOS, ] as const export type RouteProcessor5ChainId = (typeof ROUTE_PROCESSOR_5_SUPPORTED_CHAIN_IDS)[number] diff --git a/protocols/route-processor/deployments/cronos/RouteProcessor5.json b/protocols/route-processor/deployments/cronos/RouteProcessor5.json new file mode 100644 index 0000000000..3a82abe84a --- /dev/null +++ b/protocols/route-processor/deployments/cronos/RouteProcessor5.json @@ -0,0 +1,704 @@ +{ + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_bentoBox", + "type": "address" + }, + { + "internalType": "address[]", + "name": "priviledgedUserList", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "MinimalOutputBalanceViolation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Route", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "algebraSwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bentoBox", + "outputs": [ + { + "internalType": "contract IBentoBoxMinimal", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "pancakeV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "priviledgedUsers", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueInput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "priviledge", + "type": "bool" + } + ], + "name": "setPriviledge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "transferValueAndprocessRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x5f8d1f56edd72396a99580eebb17d6a76d43f8a62d4436cc6ad9c62ae89a0976", + "receipt": { + "to": null, + "from": "0x282607716D9B4fDD0B094d5864fac56313f5e665", + "contractAddress": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "transactionIndex": 0, + "gasUsed": "3489875", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000020000000000000000000000000000000000000001000000000000000000000000000000000000000000040000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000000000000000000000000000", + "blockHash": "0xc26f56a5718a14a9621b1c876e7b7c0b71efc7fedd74717275ac5326e104c9e4", + "transactionHash": "0x5f8d1f56edd72396a99580eebb17d6a76d43f8a62d4436cc6ad9c62ae89a0976", + "logs": [ + { + "transactionIndex": 0, + "blockNumber": 15236244, + "transactionHash": "0x5f8d1f56edd72396a99580eebb17d6a76d43f8a62d4436cc6ad9c62ae89a0976", + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000282607716d9b4fdd0b094d5864fac56313f5e665" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0xc26f56a5718a14a9621b1c876e7b7c0b71efc7fedd74717275ac5326e104c9e4" + } + ], + "blockNumber": 15236244, + "cumulativeGasUsed": "3489875", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000000", + [] + ], + "numDeployments": 1, + "solcInputHash": "9252879aaeb02fabe759ce8768addec4", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bentoBox\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"priviledgedUserList\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"MinimalOutputBalanceViolation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"Route\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"algebraSwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"pancakeV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"priviledgedUsers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"priviledge\",\"type\":\"bool\"}],\"name\":\"setPriviledge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"transferValueAndprocessRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"Ilya Lyalin\",\"kind\":\"dev\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IAlgebraPoolActions#swap call\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the PancakeV3Pool#swap call\"}},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"route\":\"Route to process\",\"to\":\"Where to transfer output tokens\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IUniswapV3PoolActions#swap call\"}}},\"title\":\"A route processor for the Sushi Aggregator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\"},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Processes the route generated off-chain. Has a lock\"},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value of input tokens to and then processes the route\"},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"processes the route and sends amount of output token to \"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value to and then processes the route\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RouteProcessor5.sol\":\"RouteProcessor5\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\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 Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.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 function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\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\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\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 * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\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\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/InputStream.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\n/** @notice Simple read stream */\\nlibrary InputStream {\\n\\n /** @notice Creates stream from data\\n * @param data data\\n */\\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\\n assembly {\\n stream := mload(0x40)\\n mstore(0x40, add(stream, 64))\\n mstore(stream, data)\\n let length := mload(data)\\n mstore(add(stream, 32), add(data, length))\\n }\\n }\\n\\n /** @notice Checks if stream is not empty\\n * @param stream stream\\n */\\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\\n uint256 pos;\\n uint256 finish;\\n assembly {\\n pos := mload(stream)\\n finish := mload(add(stream, 32))\\n }\\n return pos < finish;\\n }\\n\\n /** @notice Reads uint8 from the stream\\n * @param stream stream\\n */\\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 1)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint16 from the stream\\n * @param stream stream\\n */\\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 2)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint24 from the stream\\n * @param stream stream\\n */\\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 3)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint32 from the stream\\n * @param stream stream\\n */\\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 4)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint256 from the stream\\n * @param stream stream\\n */\\n function readUint(uint256 stream) internal pure returns (uint256 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes32 from the stream\\n * @param stream stream\\n */\\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads address from the stream\\n * @param stream stream\\n */\\n function readAddress(uint256 stream) internal pure returns (address res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 20)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes from the stream\\n * @param stream stream\\n */\\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\\n assembly {\\n let pos := mload(stream)\\n res := add(pos, 32)\\n let length := mload(res)\\n mstore(stream, add(res, length))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x24e24bd0e49cbddacbf3b26bcd4bdffac63d11f3259bc05bc93c0835e8ff5300\",\"license\":\"UNLICENSED\"},\"contracts/RouteProcessor5.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '../interfaces/IUniswapV2Pair.sol';\\nimport '../interfaces/IUniswapV3Pool.sol';\\nimport '../interfaces/ITridentCLPool.sol';\\nimport '../interfaces/IBentoBoxMinimal.sol';\\nimport '../interfaces/IPool.sol';\\nimport '../interfaces/IWETH.sol';\\nimport '../interfaces/ICurve.sol';\\nimport './InputStream.sol';\\nimport './Utils.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\\n\\nuint8 constant LOCKED = 2;\\nuint8 constant NOT_LOCKED = 1;\\nuint8 constant PAUSED = 2;\\nuint8 constant NOT_PAUSED = 1;\\n\\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\nuint160 constant MIN_SQRT_RATIO = 4295128739;\\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n/// @title A route processor for the Sushi Aggregator\\n/// @author Ilya Lyalin\\ncontract RouteProcessor5 is Ownable {\\n using SafeERC20 for IERC20;\\n using Utils for IERC20;\\n using Utils for address;\\n using SafeERC20 for IERC20Permit;\\n using InputStream for uint256;\\n\\n event Route(\\n address indexed from, \\n address to, \\n address indexed tokenIn, \\n address indexed tokenOut, \\n uint256 amountIn, \\n uint256 amountOutMin,\\n uint256 amountOut\\n );\\n\\n error MinimalOutputBalanceViolation(uint256 amountOut);\\n\\n IBentoBoxMinimal public immutable bentoBox;\\n mapping (address => bool) public priviledgedUsers;\\n address private lastCalledPool;\\n\\n uint8 private unlocked = NOT_LOCKED;\\n uint8 private paused = NOT_PAUSED;\\n modifier lock() {\\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\\n unlocked = LOCKED;\\n _;\\n unlocked = NOT_LOCKED;\\n }\\n\\n modifier onlyOwnerOrPriviledgedUser() {\\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \\\"RP: caller is not the owner or a privileged user\\\");\\n _;\\n }\\n\\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\\n bentoBox = IBentoBoxMinimal(_bentoBox);\\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n\\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\\n priviledgedUsers[priviledgedUserList[i]] = true;\\n }\\n }\\n\\n function setPriviledge(address user, bool priviledge) external onlyOwner {\\n priviledgedUsers[user] = priviledge;\\n }\\n\\n function pause() external onlyOwnerOrPriviledgedUser {\\n paused = PAUSED;\\n }\\n\\n function resume() external onlyOwnerOrPriviledgedUser {\\n paused = NOT_PAUSED;\\n }\\n\\n /// @notice For native unwrapping\\n receive() external payable {}\\n\\n /// @notice Processes the route generated off-chain. Has a lock\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @param to Where to transfer output tokens\\n /// @param route Route to process\\n /// @return amountOut Actual amount of the output token\\n function processRoute(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function transferValueAndprocessRoute(\\n address transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n transferValueTo.transferNative(amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value of input tokens to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueInput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n \\n /// @notice processes the route and sends amount of output token to \\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueOutput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\\n }\\n\\n /// @notice Processes the route generated off-chain\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteInternal(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) private returns (uint256 amountOut) {\\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\\n\\n uint256 realAmountIn = amountIn;\\n {\\n uint256 step = 0;\\n uint256 stream = InputStream.createStream(route);\\n while (stream.isNotEmpty()) {\\n uint8 commandCode = stream.readUint8();\\n if (commandCode == 1) {\\n uint256 usedAmount = processMyERC20(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 2) processUserERC20(stream, amountIn);\\n else if (commandCode == 3) {\\n uint256 usedAmount = processNative(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 4) processOnePool(stream);\\n else if (commandCode == 5) processInsideBento(stream);\\n else if (commandCode == 6) applyPermit(tokenIn, stream);\\n else revert('RouteProcessor: Unknown command code');\\n ++step;\\n }\\n }\\n\\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\\n if (tokenIn != Utils.NATIVE_ADDRESS)\\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\\n \\n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\\n\\n amountOut = balanceOutFinal - balanceOutInitial;\\n\\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\\n }\\n\\n /// @notice Applies ERC-2612 permit\\n /// @param tokenIn permitted token\\n /// @param stream Streamed program\\n function applyPermit(address tokenIn, uint256 stream) private {\\n uint256 value = stream.readUint();\\n uint256 deadline = stream.readUint();\\n uint8 v = stream.readUint8();\\n bytes32 r = stream.readBytes32();\\n bytes32 s = stream.readBytes32();\\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\\n }\\n }\\n\\n /// @notice Processes native coin: call swap for all pools that swap from native coin\\n /// @param stream Streamed program\\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\\n amountTotal = address(this).balance;\\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token from this contract balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\\n address token = stream.readAddress();\\n amountTotal = IERC20(token).balanceOf(address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n \\n /// @notice Processes ERC20 token from msg.sender balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n /// @param amountTotal Amount of tokens to take from msg.sender\\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\\n address token = stream.readAddress();\\n distributeAndSwap(stream, msg.sender, token, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token for cases when the token has only one output pool\\n /// @notice In this case liquidity is already at pool balance. This is an optimization\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processOnePool(uint256 stream) private {\\n address token = stream.readAddress();\\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\\n }\\n\\n /// @notice Processes Bento tokens \\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processInsideBento(uint256 stream) private {\\n address token = stream.readAddress();\\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n\\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountTotal Total amount of tokenIn for swaps \\n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\\n uint8 num = stream.readUint8();\\n unchecked {\\n for (uint256 i = 0; i < num; ++i) {\\n uint16 share = stream.readUint16();\\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\\n amountTotal -= amount;\\n swap(stream, from, tokenIn, amount);\\n }\\n }\\n }\\n\\n /// @notice Makes swap\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 poolType = stream.readUint8();\\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\\n else revert('RouteProcessor: Unknown pool type');\\n }\\n\\n /// @notice Wraps/unwraps native token\\n /// @param stream [direction & fake, recipient, wrapToken?]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 directionAndFake = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (directionAndFake & 1 == 1) { // wrap native\\n address wrapToken = stream.readAddress();\\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\\n } else { // unwrap native\\n if (directionAndFake & 2 == 0) {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IWETH(tokenIn).withdraw(amountIn);\\n }\\n to.transferNative(amountIn);\\n }\\n }\\n\\n /// @notice Bridge/unbridge tokens to/from Bento\\n /// @param stream [direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (direction > 0) { // outside to Bento\\n // deposit to arbitrary recipient is possible only from address(bentoBox)\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\\n else {\\n // tokens already are at address(bentoBox)\\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\\n bentoBox.strategyData(tokenIn).balance -\\n bentoBox.totals(tokenIn).elastic;\\n }\\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\\n } else { // Bento to outside\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\\n }\\n }\\n\\n /// @notice UniswapV2 pool swap\\n /// @param stream [pool, direction, recipient, fee]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\\n\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\\n\\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\\n\\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\\n }\\n\\n /// @notice Trident pool swap\\n /// @param stream [pool, swapData]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bytes memory swapData = stream.readBytes();\\n\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, pool, amountIn);\\n }\\n \\n IPool(pool).swap(swapData);\\n }\\n\\n /// @notice UniswapV3 pool swap\\n /// @param stream [pool, direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bool zeroForOne = stream.readUint8() > 0;\\n address recipient = stream.readAddress();\\n\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\\n\\n lastCalledPool = pool;\\n IUniswapV3Pool(pool).swap(\\n recipient,\\n zeroForOne,\\n int256(amountIn),\\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\\n abi.encode(tokenIn)\\n );\\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) public {\\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\\n \\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n (address tokenIn) = abi.decode(data, (address));\\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\\n function algebraSwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\\n function pancakeV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 poolType = stream.readUint8();\\n int128 fromIndex = int8(stream.readUint8());\\n int128 toIndex = int8(stream.readUint8());\\n address to = stream.readAddress();\\n address tokenOut = stream.readAddress();\\n\\n uint256 amountOut;\\n if (tokenIn == Utils.NATIVE_ADDRESS) {\\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\\n } else {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IERC20(tokenIn).approveSafe(pool, amountIn);\\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n else {\\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\\n amountOut = balanceAfter - balanceBefore;\\n }\\n }\\n\\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\\n }\\n}\\n\",\"keccak256\":\"0xcd53a7f473f1847d44c42777a194203cbff02b8c761cb2935402401f57c918a2\",\"license\":\"UNLICENSED\"},\"contracts/Utils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\n\\nlibrary Utils {\\n using SafeERC20 for IERC20;\\n\\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n /**\\n * @dev returns user's balance of token (or native)\\n */\\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\\n if (token == NATIVE_ADDRESS) return address(user).balance;\\n else return IERC20(token).balanceOf(user);\\n }\\n\\n /**\\n * @dev transfers native with correct revert bubble up\\n */\\n function transferNative(address to, uint256 amount) internal {\\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\\n if (!success) {\\n assembly {\\n revert(add(32, returnBytes), mload(returnBytes))\\n }\\n }\\n }\\n\\n /**\\n * @dev transfers ERC20 or native\\n */\\n function transferAny(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\\n else IERC20(token).safeTransfer(to, amount);\\n }\\n\\n /**\\n * @dev transfers from ERC20 or transfers native\\n */\\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n (bool success, bytes memory data) = address(token).call(\\n abi.encodeWithSelector(token.approve.selector, spender, amount)\\n );\\n return success && (data.length == 0 || abi.decode(data, (bool)));\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \\n * current allowance are not zero simultaniously (USDT for example). \\n * In second case it tries to set allowance to 0, and then back to amount.\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n return approveStable(token, spender, amount) \\n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\\n }\\n}\\n\",\"keccak256\":\"0x8c8439edc00b403abd3f34be75a06b1fe71152644ae9f19488af596bbc534ffe\",\"license\":\"UNLICENSED\"},\"interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\nstruct StrategyData {\\n uint64 strategyStartDate;\\n uint64 targetPercentage;\\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n function strategyData(address token) external view returns (StrategyData memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0x0c12eba7a5b9d22d37ab8883fe22d6a312a90682809dbd11c43f8e6ceaff73bf\",\"license\":\"UNLICENSED\"},\"interfaces/ICurve.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\ninterface ICurve {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\\n}\\n\\ninterface ICurveLegacy {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\\n}\\n\\n\",\"keccak256\":\"0x3d4940b3583e06dde20f12e92d2f6ac573b3f64bdaa1e8f480656a3763852518\",\"license\":\"UNLICENSED\"},\"interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/ITridentCLPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface ITridentCLPool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bool unwrapBento,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x572376b80c86a94692b0e27e6e63790b763295e32ba1f956c1d331fc1296de8d\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IUniswapV2Pair.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Pair {\\n event Approval(address indexed owner, address indexed spender, uint value);\\n event Transfer(address indexed from, address indexed to, uint value);\\n\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function allowance(address owner, address spender) external view returns (uint);\\n\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address to, uint value) external returns (bool);\\n function transferFrom(address from, address to, uint value) external returns (bool);\\n\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n function nonces(address owner) external view returns (uint);\\n\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n event Mint(address indexed sender, uint amount0, uint amount1);\\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\\n event Swap(\\n address indexed sender,\\n uint amount0In,\\n uint amount1In,\\n uint amount0Out,\\n uint amount1Out,\\n address indexed to\\n );\\n event Sync(uint112 reserve0, uint112 reserve1);\\n\\n function MINIMUM_LIQUIDITY() external pure returns (uint);\\n function factory() external view returns (address);\\n function token0() external view returns (address);\\n function token1() external view returns (address);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\\n function price0CumulativeLast() external view returns (uint);\\n function price1CumulativeLast() external view returns (uint);\\n function kLast() external view returns (uint);\\n\\n function mint(address to) external returns (uint liquidity);\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function skim(address to) external;\\n function sync() external;\\n\\n function initialize(address, address) external;\\n}\",\"keccak256\":\"0x08f9a63b34855eec941be8d36a04424f1a1725a2c030373fcef3afeb480ca385\",\"license\":\"GPL-3.0\"},\"interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IUniswapV3Pool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x2a4d7c6120e613f0e95d4dc8c650efb9b59e3c25c64e3e5c0a379281500f0a79\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IWETH.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0xae8529ae159f784b90fdcd0629bd03bf7b68accc81edccac53357ad08406a378\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}", + "bytecode": "0x60a06040526002805461ffff60a01b191661010160a01b1790553480156200002657600080fd5b50604051620040a3380380620040a383398101604081905262000049916200016e565b6200005433620000eb565b6001600160a01b038216608052600280546001600160a01b031916600117905560005b8151811015620000e25760018060008484815181106200009b576200009b62000257565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000d9816200026d565b91505062000077565b50505062000297565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200015357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200018257600080fd5b6200018d836200013b565b602084810151919350906001600160401b0380821115620001ad57600080fd5b818601915086601f830112620001c257600080fd5b815181811115620001d757620001d762000158565b8060051b604051601f19603f83011681018181108582111715620001ff57620001ff62000158565b6040529182528482019250838101850191898311156200021e57600080fd5b938501935b82851015620002475762000237856200013b565b8452938501939285019262000223565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200029057634e487b7160e01b600052601160045260246000fd5b5060010190565b608051613da3620003006000396000818161018d01528181611798015281816127380152818161279d01528181612807015281816128cc0152818161297901528181612a5d01528181612b6401528181612c1001528181612cdf0152612df10152613da36000f3fe6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "deployedBytecode": "0x6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "devdoc": { + "author": "Ilya Lyalin", + "kind": "dev", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IAlgebraPoolActions#swap call" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the PancakeV3Pool#swap call" + } + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "route": "Route to process", + "to": "Where to transfer output tokens", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IUniswapV3PoolActions#swap call" + } + } + }, + "title": "A route processor for the Sushi Aggregator", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IAlgebraPool#swap." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via PancakeV3Pool#swap." + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "notice": "Processes the route generated off-chain. Has a lock" + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value of input tokens to and then processes the route" + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "processes the route and sends amount of output token to " + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value to and then processes the route" + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 8573, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "priviledgedUsers", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 8575, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "lastCalledPool", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 8578, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "unlocked", + "offset": 20, + "slot": "2", + "type": "t_uint8" + }, + { + "astId": 8581, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "paused", + "offset": 21, + "slot": "2", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/cronos/solcInputs/9252879aaeb02fabe759ce8768addec4.json b/protocols/route-processor/deployments/cronos/solcInputs/9252879aaeb02fabe759ce8768addec4.json new file mode 100644 index 0000000000..c6762a8dc1 --- /dev/null +++ b/protocols/route-processor/deployments/cronos/solcInputs/9252879aaeb02fabe759ce8768addec4.json @@ -0,0 +1,98 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" + }, + "contracts/Approve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\n\nlibrary Approve {\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "contracts/InputStream.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" + }, + "contracts/RouteProcessor.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport './InputStream.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\naddress constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Okavango\ncontract RouteProcessor {\n using SafeERC20 for IERC20;\n using InputStream for uint256;\n\n IBentoBoxMinimal public immutable bentoBox;\n\n uint private unlocked = 1;\n modifier lock() {\n require(unlocked == 1, 'RouteProcessor is locked');\n unlocked = 2;\n _;\n unlocked = 1;\n }\n\n constructor(address _bentoBox) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n (bool success, bytes memory returnBytes) = transferValueTo.call{value: amountValueTransfer}('');\n require(success, string(abi.encodePacked(returnBytes)));\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 amountInAcc = 0;\n uint256 balanceInitial = tokenOut == NATIVE_ADDRESS ? \n address(to).balance : IERC20(tokenOut).balanceOf(to);\n\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode < 20) {\n if (commandCode == 10)\n swapUniswapPool(stream); // Sushi/Uniswap pool swap\n else if (commandCode == 4)\n distributeERC20Shares(stream); // distribute ERC20 tokens from this router to pools\n else if (commandCode == 3)\n amountInAcc += distributeERC20Amounts(stream, tokenIn); // initial distribution\n else if (commandCode == 5)\n amountInAcc += wrapAndDistributeERC20Amounts(stream); // wrap natives and initial distribution \n else if (commandCode == 6) \n unwrapNative(to, stream);\n else if (commandCode == 7)\n amountInAcc += distributeERC20AmountsFromRP(stream, tokenIn); // initial distribution\n else revert('Unknown command code');\n } else if (commandCode < 24) {\n if (commandCode == 20) bentoDepositAmountFromBento(stream, tokenIn);\n else if (commandCode == 21) swapTrident(stream);\n else if (commandCode == 23) bentoWithdrawShareFromRP(stream, tokenIn);\n else revert('Unknown command code');\n } else {\n if (commandCode == 24) amountInAcc += distributeBentoShares(stream, tokenIn);\n else if (commandCode == 25) distributeBentoPortions(stream);\n else if (commandCode == 26) bentoDepositAllFromBento(stream);\n else if (commandCode == 27) bentoWithdrawAllFromRP(stream);\n else revert('Unknown command code');\n }\n }\n\n require(amountInAcc == amountIn, 'Wrong amountIn value');\n uint256 balanceFinal = tokenOut == NATIVE_ADDRESS ? \n address(to).balance : IERC20(tokenOut).balanceOf(to);\n require(balanceFinal >= balanceInitial + amountOutMin, 'Minimal ouput balance violation');\n\n amountOut = balanceFinal - balanceInitial;\n }\n\n /// @notice Transfers input tokens sent to BentoBox to a pool\n /// @notice Expected to be called for initial liquidity transfer from user to BentoBox, so we know exact amounts\n /// @param stream [Pool, Amount]. Pool into which an amount of tokens will be transferred\n /// @param token Address of the token to transfer\n function bentoDepositAmountFromBento(uint256 stream, address token) private {\n address to = stream.readAddress();\n uint256 amount = stream.readUint();\n bentoBox.deposit(token, address(bentoBox), to, amount, 0);\n }\n\n /// @notice Transfers all available input tokens from BentoBox to a pool\n /// @param stream [Pool, Token]. Pool into which all tokens will be transferred \n function bentoDepositAllFromBento(uint256 stream) private {\n address to = stream.readAddress();\n address token = stream.readAddress();\n\n uint256 amount = IERC20(token).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(token).balance -\n bentoBox.totals(token).elastic;\n bentoBox.deposit(token, address(bentoBox), to, amount, 0);\n }\n\n /// @notice Withdraws BentoBox tokens from BentoBox to an address\n /// @param stream [To, Amount]. Destination where an amount of token will be transferred\n /// @param token Token to transfer\n function bentoWithdrawShareFromRP(uint256 stream, address token) private {\n address to = stream.readAddress();\n uint256 amount = stream.readUint();\n bentoBox.withdraw(token, address(this), to, amount, 0);\n }\n\n /// @notice Withdraws all available BentoBox tokens from BentoBox to an address\n /// @param stream [Token, To]. Token which will be transferred to a destination\n function bentoWithdrawAllFromRP(uint256 stream) private {\n address token = stream.readAddress();\n address to = stream.readAddress();\n uint256 amount = bentoBox.balanceOf(token, address(this));\n bentoBox.withdraw(token, address(this), to, 0, amount);\n }\n\n /// @notice Performs a Trident pool swap\n /// @param stream [Pool, SwapData]. Pool against a swap defined by SwapData will be executed\n function swapTrident(uint256 stream) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n IPool(pool).swap(swapData);\n }\n\n /// @notice Performs a Sushi/UniswapV2 pool swap\n /// @param stream [Pool, TokenIn, Direction, To]\n /// @return amountOut Amount of the output token\n function swapUniswapPool(uint256 stream) private returns (uint256 amountOut) {\n address pool = stream.readAddress();\n address tokenIn = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n\n uint256 amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn;\n uint256 amountInWithFee = amountIn * 997;\n amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Distributes input ERC20 tokens from msg.sender to addresses. Tokens should be approved\n /// @notice Expected to be called for initial liquidity transfer from the user to pools, so we know exact amounts\n /// @param stream [ArrayLength, ...[To, Amount][]]. An array of destinations and token amounts\n /// @param token Token to distribute\n /// @return amountTotal Total amount distributed\n function distributeERC20Amounts(uint256 stream, address token) private returns (uint256 amountTotal) {\n uint8 num = stream.readUint8();\n amountTotal = 0;\n for (uint256 i = 0; i < num; ++i) {\n address to = stream.readAddress();\n uint256 amount = stream.readUint();\n amountTotal += amount;\n IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n }\n\n /// @notice Distributes input ERC20 tokens from this contract to addresses. Tokens should be approved\n /// @notice Expected to be called for initial liquidity transfer from the user to pools, so we know exact amounts\n /// @param stream [ArrayLength, ...[To, Amount][]]. An array of destinations and token amounts\n /// @param token Token to distribute\n /// @return amountTotal Total amount distributed\n function distributeERC20AmountsFromRP(uint256 stream, address token) private returns (uint256 amountTotal) {\n uint8 num = stream.readUint8();\n amountTotal = 0;\n for (uint256 i = 0; i < num; ++i) {\n address to = stream.readAddress();\n uint256 amount = stream.readUint();\n amountTotal += amount;\n IERC20(token).safeTransfer(to, amount);\n }\n }\n\n /// @notice Wraps all native inputs and distributes wrapped ERC20 tokens from RouteProcessor to addresses\n /// @notice Expected to be called for initial liquidity transfer from the user to pools, so we know exact amounts\n /// @param stream [WrapToken, ArrayLength, ...[To, Amount][]]. An array of destinations and token amounts\n /// @return amountTotal Total amount distributed\n function wrapAndDistributeERC20Amounts(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n IWETH(token).deposit{value: address(this).balance}();\n uint8 num = stream.readUint8();\n amountTotal = 0;\n for (uint256 i = 0; i < num; ++i) {\n address to = stream.readAddress();\n uint256 amount = stream.readUint();\n amountTotal += amount;\n IERC20(token).safeTransfer(to, amount);\n }\n require(address(this).balance == 0, \"RouteProcessor: invalid input amount\");\n }\n\n /// @notice Distributes input BentoBox tokens from msg.sender to addresses. Tokens should be approved\n /// @notice Expected to be called for initial liquidity transfer from the user to pools, so we know exact amounts\n /// @param stream [ArrayLength, ...[To, ShareAmount][]]. An array of destinations and token share amounts\n /// @param token Token to distribute\n /// @return sharesTotal Total shares distributed\n function distributeBentoShares(uint256 stream, address token) private returns (uint256 sharesTotal) {\n uint8 num = stream.readUint8();\n sharesTotal = 0;\n for (uint256 i = 0; i < num; ++i) {\n address to = stream.readAddress();\n uint256 share = stream.readUint();\n sharesTotal += share;\n bentoBox.transfer(token, msg.sender, to, share);\n }\n }\n\n /// @notice Distributes ERC20 tokens from RouteProcessor to addresses\n /// @notice Quantity for sending is determined by share in 1/65535\n /// @notice During routing we can't predict in advance the actual value of internal swaps because of slippage,\n /// @notice so we have to work with shares - not fixed amounts\n /// @param stream [Token, ArrayLength, ...[To, ShareAmount][]]. Token to distribute. An array of destinations and token share amounts\n function distributeERC20Shares(uint256 stream) private {\n address token = stream.readAddress();\n uint8 num = stream.readUint8();\n uint256 amountTotal = IERC20(token).balanceOf(address(this))\n - 1; // slot undrain protection\n\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n address to = stream.readAddress();\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / 65535;\n amountTotal -= amount;\n IERC20(token).safeTransfer(to, amount);\n }\n }\n }\n\n /// @notice Distributes BentoBox tokens from RouteProcessor to addresses\n /// @notice Quantity for sending is determined by portions in 1/65535.\n /// @notice During routing we can't predict in advance the actual value of internal swaps because of slippage,\n /// @notice so we have to work with portions - not fixed amounts\n /// @param stream [Token, ArrayLength, ...[To, ShareAmount][]]. Token to distribute. An array of destinations and token share amounts\n function distributeBentoPortions(uint256 stream) private {\n address token = stream.readAddress();\n uint8 num = stream.readUint8();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this))\n - 1; // slot undrain protection\n\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n address to = stream.readAddress();\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / 65535;\n amountTotal -= amount;\n bentoBox.transfer(token, address(this), to, amount);\n }\n }\n }\n\n /// @notice Unwraps the Native Token\n /// @param receiver Destination of the unwrapped token\n /// @param stream [Token]. Token to unwrap native\n function unwrapNative(address receiver, uint256 stream) private {\n address token = stream.readAddress();\n IWETH(token).withdraw( IERC20(token).balanceOf(address(this))\n - 1); // slot undrain protection\n payable(receiver).transfer(address(this).balance);\n }\n}\n" + }, + "contracts/RouteProcessor3_1.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport './InputStream.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\n/// version 3.1\ncontract RouteProcessor3_1 is Ownable {\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint amountIn, \n uint amountOutMin,\n uint amountOut\n );\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = 1;\n uint8 private paused = 1;\n modifier lock() {\n require(unlocked == 1, 'RouteProcessor is locked');\n require(paused == 1, 'RouteProcessor is paused');\n unlocked = 2;\n _;\n unlocked = 1;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender] == true, \"RP: caller is not the owner or a priviledged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = 2;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = 1;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n (bool success, bytes memory returnBytes) = transferValueTo.call{value: amountValueTransfer}('');\n require(success, string(abi.encodePacked(returnBytes)));\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn == NATIVE_ADDRESS ? address(this).balance : IERC20(tokenIn).balanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut == NATIVE_ADDRESS ? address(to).balance : IERC20(tokenOut).balanceOf(to);\n\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) processMyERC20(stream);\n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) processNative(stream);\n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n }\n\n uint256 balanceInFinal = tokenIn == NATIVE_ADDRESS ? address(this).balance : IERC20(tokenIn).balanceOf(msg.sender);\n require(balanceInFinal + amountIn >= balanceInInitial, 'RouteProcessor: Minimal imput balance violation');\n\n uint256 balanceOutFinal = tokenOut == NATIVE_ADDRESS ? address(to).balance : IERC20(tokenOut).balanceOf(to);\n require(balanceOutFinal >= balanceOutInitial + amountOutMin, 'RouteProcessor: Minimal ouput balance violation');\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, amountIn, amountOutMin, amountOut);\n }\n\n function applyPermit(address tokenIn, uint256 stream) private {\n //address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s)\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed process program\n function processNative(uint256 stream) private {\n uint256 amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n function processMyERC20(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed process program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / 65535;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, address(this), token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint8 num = stream.readUint8();\n\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / 65535;\n amountTotal -= amount;\n swap(stream, address(this), token, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed process program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from != address(this)) IERC20(tokenIn).safeTransferFrom(from, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n payable(to).transfer(address(this).balance);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (amountIn != 0) {\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else IERC20(tokenIn).safeTransferFrom(from, address(bentoBox), amountIn);\n } else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (amountIn > 0) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n\n if (amountIn != 0) {\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else IERC20(tokenIn).safeTransferFrom(from, pool, amountIn);\n }\n // without 'else' in order to support tax tokens\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * 997;\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (amountIn != 0) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from != address(this)) {\n require(from == msg.sender, 'swapUniV3: unexpected from address');\n IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n }\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n\n // Normally, RouteProcessor shouldn't have any liquidity on board\n // If some liquidity exists, it is sweept by the next user that makes swap through these tokens\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n}\n" + }, + "contracts/RouteProcessor3_2.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport './InputStream.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\n/// version 3.2\ncontract RouteProcessor3_2 is Ownable {\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint amountIn, \n uint amountOutMin,\n uint amountOut\n );\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = 1;\n uint8 private paused = 1;\n modifier lock() {\n require(unlocked == 1, 'RouteProcessor is locked');\n require(paused == 1, 'RouteProcessor is paused');\n unlocked = 2;\n _;\n unlocked = 1;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender] == true, \"RP: caller is not the owner or a priviledged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = 2;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = 1;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n (bool success, bytes memory returnBytes) = transferValueTo.call{value: amountValueTransfer}('');\n require(success, string(abi.encodePacked(returnBytes)));\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn == NATIVE_ADDRESS ? address(this).balance : IERC20(tokenIn).balanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut == NATIVE_ADDRESS ? address(to).balance : IERC20(tokenOut).balanceOf(to);\n\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) processMyERC20(stream);\n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) processNative(stream);\n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n }\n\n uint256 balanceInFinal = tokenIn == NATIVE_ADDRESS ? address(this).balance : IERC20(tokenIn).balanceOf(msg.sender);\n require(balanceInFinal + amountIn >= balanceInInitial, 'RouteProcessor: Minimal imput balance violation');\n\n uint256 balanceOutFinal = tokenOut == NATIVE_ADDRESS ? address(to).balance : IERC20(tokenOut).balanceOf(to);\n require(balanceOutFinal >= balanceOutInitial + amountOutMin, 'RouteProcessor: Minimal ouput balance violation');\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, amountIn, amountOutMin, amountOut);\n }\n\n function applyPermit(address tokenIn, uint256 stream) private {\n //address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s)\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed process program\n function processNative(uint256 stream) private {\n uint256 amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n function processMyERC20(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed process program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / 65535;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, address(this), token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint8 num = stream.readUint8();\n\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / 65535;\n amountTotal -= amount;\n swap(stream, address(this), token, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed process program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from != address(this)) IERC20(tokenIn).safeTransferFrom(from, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n payable(to).transfer(address(this).balance);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (amountIn != 0) {\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else IERC20(tokenIn).safeTransferFrom(from, address(bentoBox), amountIn);\n } else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (amountIn > 0) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (amountIn != 0) {\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else IERC20(tokenIn).safeTransferFrom(from, pool, amountIn);\n }\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * 997;\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (amountIn != 0) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from != address(this)) {\n require(from == msg.sender, 'swapUniV3: unexpected from address');\n IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n }\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n\n // Normally, RouteProcessor shouldn't have any liquidity on board\n // If some liquidity exists, it is sweept by the next user that makes swap through these tokens\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n}\n" + }, + "contracts/RouteProcessor3.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport './InputStream.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\n/// version 2.1\ncontract RouteProcessor3 is Ownable {\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint amountIn, \n uint amountOutMin,\n uint amountOut\n );\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = 1;\n uint8 private paused = 1;\n modifier lock() {\n require(unlocked == 1, 'RouteProcessor is locked');\n require(paused == 1, 'RouteProcessor is paused');\n unlocked = 2;\n _;\n unlocked = 1;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender] == true, \"RP: caller is not the owner or a priviledged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = 2;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = 1;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n (bool success, bytes memory returnBytes) = transferValueTo.call{value: amountValueTransfer}('');\n require(success, string(abi.encodePacked(returnBytes)));\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn == NATIVE_ADDRESS ? address(this).balance : IERC20(tokenIn).balanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut == NATIVE_ADDRESS ? address(to).balance : IERC20(tokenOut).balanceOf(to);\n\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) processMyERC20(stream);\n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) processNative(stream);\n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n }\n\n uint256 balanceInFinal = tokenIn == NATIVE_ADDRESS ? address(this).balance : IERC20(tokenIn).balanceOf(msg.sender);\n require(balanceInFinal + amountIn >= balanceInInitial, 'RouteProcessor: Minimal imput balance violation');\n\n uint256 balanceOutFinal = tokenOut == NATIVE_ADDRESS ? address(to).balance : IERC20(tokenOut).balanceOf(to);\n require(balanceOutFinal >= balanceOutInitial + amountOutMin, 'RouteProcessor: Minimal ouput balance violation');\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, amountIn, amountOutMin, amountOut);\n }\n\n function applyPermit(address tokenIn, uint256 stream) private {\n //address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s)\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed process program\n function processNative(uint256 stream) private {\n uint256 amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n function processMyERC20(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed process program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / 65535;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, address(this), token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint8 num = stream.readUint8();\n\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / 65535;\n amountTotal -= amount;\n swap(stream, address(this), token, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed process program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from != address(this)) IERC20(tokenIn).safeTransferFrom(from, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n payable(to).transfer(address(this).balance);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (amountIn != 0) {\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else IERC20(tokenIn).safeTransferFrom(from, address(bentoBox), amountIn);\n } else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (amountIn > 0) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n\n if (amountIn != 0) {\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else IERC20(tokenIn).safeTransferFrom(from, pool, amountIn);\n } else amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * 997;\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (amountIn != 0) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from != address(this)) {\n require(from == msg.sender, 'swapUniV3: unexpected from address');\n IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n }\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n\n // Normally, RouteProcessor shouldn't have any liquidity on board\n // If some liquidity exists, it is sweept by the next user that makes swap through these tokens\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n}\n" + }, + "contracts/RouteProcessor4.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Approve.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor4 is Ownable {\n using SafeERC20 for IERC20;\n using Approve for IERC20;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n (bool success, bytes memory returnBytes) = transferValueTo.call{value: amountValueTransfer}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn == NATIVE_ADDRESS ? 0 : IERC20(tokenIn).balanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut == NATIVE_ADDRESS ? address(to).balance : IERC20(tokenOut).balanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn == NATIVE_ADDRESS ? 0 : IERC20(tokenIn).balanceOf(msg.sender);\n require(balanceInFinal + amountIn >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut == NATIVE_ADDRESS ? address(to).balance : IERC20(tokenOut).balanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n (bool success,)= payable(to).call{value: amountIn}(\"\");\n require(success, \"RouteProcessor.wrapNative: Native token transfer failed\");\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = IERC20(tokenOut).balanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = IERC20(tokenOut).balanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) { \n if(tokenOut == NATIVE_ADDRESS) {\n (bool success,)= payable(to).call{value: amountOut}(\"\");\n require(success, \"RouteProcessor.swapCurve: Native token transfer failed\");\n } else {\n IERC20(tokenOut).safeTransfer(to, amountOut);\n }\n }\n }\n}\n" + }, + "contracts/RouteProcessor5.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" + }, + "contracts/Utils.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "interfaces/IBentoBoxMinimal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" + }, + "interfaces/ICurve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" + }, + "interfaces/IPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" + }, + "interfaces/ITridentCLPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file From d57be9a6c0cd8e2813e1c5faaeeb439844173030 Mon Sep 17 00:00:00 2001 From: 0xMasayoshi <0xMasayoshi@protonmail.com> Date: Thu, 8 Aug 2024 13:03:24 +0700 Subject: [PATCH 097/125] chore: set feeRecipient to TokenChomper --- .../lib/wagmi/hooks/trade/use-client-trade.ts | 8 +- apps/web/test/swap/scripts/generate-swaps.ts | 8 +- .../react-query/src/hooks/trade/useTrade.ts | 8 +- packages/sushi/src/config/index.ts | 1 + packages/sushi/src/config/route-processor.ts | 1 - packages/sushi/src/config/token-chomper.ts | 81 +++++++++++++++++++ 6 files changed, 94 insertions(+), 13 deletions(-) create mode 100644 packages/sushi/src/config/token-chomper.ts diff --git a/apps/web/src/lib/wagmi/hooks/trade/use-client-trade.ts b/apps/web/src/lib/wagmi/hooks/trade/use-client-trade.ts index bc55cfd510..b5be669e12 100644 --- a/apps/web/src/lib/wagmi/hooks/trade/use-client-trade.ts +++ b/apps/web/src/lib/wagmi/hooks/trade/use-client-trade.ts @@ -8,10 +8,10 @@ import { useMemo } from 'react' import { getBigInt } from 'sushi' import { calculateFee } from 'sushi/calculate' import { - MULTISIG_ADDRESS, ROUTE_PROCESSOR_5_ADDRESS, - isMultisigChainId, + TOKEN_CHOMPER_ADDRESS, isRouteProcessor5ChainId, + isTokenChomperChainId, isWNativeSupported, } from 'sushi/config' import { Amount, Native, Price } from 'sushi/currency' @@ -133,8 +133,8 @@ export const useClientTrade = ( ? ProcessFunction.ProcessRouteWithTransferValueOutput : ProcessFunction.ProcessRoute, chargeFee - ? isMultisigChainId(chainId) - ? MULTISIG_ADDRESS[chainId] + ? isTokenChomperChainId(chainId) + ? TOKEN_CHOMPER_ADDRESS[chainId] : '0xFF64C2d5e23e9c48e8b42a23dc70055EEC9ea098' : undefined, chargeFee ? calculateFee(minAmountOut) : undefined, diff --git a/apps/web/test/swap/scripts/generate-swaps.ts b/apps/web/test/swap/scripts/generate-swaps.ts index 70fcf5be6a..8d171e3d2a 100644 --- a/apps/web/test/swap/scripts/generate-swaps.ts +++ b/apps/web/test/swap/scripts/generate-swaps.ts @@ -3,8 +3,8 @@ import { type UseTradeParams, tradeValidator02 } from '@sushiswap/react-query' import { ChainId } from 'sushi/chain' import { API_BASE_URL, - // MULTISIG_ADDRESS, - // isMultisigChainId, + // TOKEN_CHOMPER_ADDRESS, + // isTokenChomperChainId, publicClientConfig, } from 'sushi/config' import { Amount, Native, USDC, USDT, WBTC } from 'sushi/currency' @@ -86,8 +86,8 @@ const getSwapApiResult = async ({ // params.searchParams.set('enableFee', 'true') // params.searchParams.set( // 'feeReceiver', - // isMultisigChainId(chainId) - // ? MULTISIG_ADDRESS[chainId] + // isTokenChomperChainId(chainId) + // ? TOKEN_CHOMPER_ADDRESS[chainId] // : '0xFF64C2d5e23e9c48e8b42a23dc70055EEC9ea098', // ) // params.searchParams.set('fee', '0.0025') diff --git a/packages/react-query/src/hooks/trade/useTrade.ts b/packages/react-query/src/hooks/trade/useTrade.ts index d5d5428231..abd92dc38b 100644 --- a/packages/react-query/src/hooks/trade/useTrade.ts +++ b/packages/react-query/src/hooks/trade/useTrade.ts @@ -8,9 +8,9 @@ import { useCallback, useMemo } from 'react' import { slippageAmount } from 'sushi/calculate' import { API_BASE_URL, - MULTISIG_ADDRESS, - isMultisigChainId, + TOKEN_CHOMPER_ADDRESS, isRouteProcessor5ChainId, + isTokenChomperChainId, isWNativeSupported, } from 'sushi/config' import { Amount, Native, Price, type Type } from 'sushi/currency' @@ -78,8 +78,8 @@ export const useTradeQuery = ( params.searchParams.set('enableFee', 'true') params.searchParams.set( 'feeReceiver', - isMultisigChainId(chainId) - ? MULTISIG_ADDRESS[chainId] + isTokenChomperChainId(chainId) + ? TOKEN_CHOMPER_ADDRESS[chainId] : '0xFF64C2d5e23e9c48e8b42a23dc70055EEC9ea098', ) params.searchParams.set('fee', '0.0025') diff --git a/packages/sushi/src/config/index.ts b/packages/sushi/src/config/index.ts index d2b3a73e2b..fa3633751f 100644 --- a/packages/sushi/src/config/index.ts +++ b/packages/sushi/src/config/index.ts @@ -21,6 +21,7 @@ export * from './stargate.js' export * from './sushiswap-v2.js' export * from './sushiswap-v3.js' export * from './sushixswap.js' +export * from './token-chomper.js' export * from './token-security.js' export * from './trident.js' export * from './uniswap-v2.js' diff --git a/packages/sushi/src/config/route-processor.ts b/packages/sushi/src/config/route-processor.ts index 47cc29408e..115730950a 100644 --- a/packages/sushi/src/config/route-processor.ts +++ b/packages/sushi/src/config/route-processor.ts @@ -378,7 +378,6 @@ export const ROUTE_PROCESSOR_5_SUPPORTED_CHAIN_IDS = [ ChainId.BLAST, ChainId.SKALE_EUROPA, ChainId.ROOTSTOCK, - ChainId.CRONOS, ] as const export type RouteProcessor5ChainId = (typeof ROUTE_PROCESSOR_5_SUPPORTED_CHAIN_IDS)[number] diff --git a/packages/sushi/src/config/token-chomper.ts b/packages/sushi/src/config/token-chomper.ts new file mode 100644 index 0000000000..5319136eab --- /dev/null +++ b/packages/sushi/src/config/token-chomper.ts @@ -0,0 +1,81 @@ +import { ChainId } from '../chain/index.js' + +export const TOKEN_CHOMPER_CHAIN_IDS = [ + ChainId.ETHEREUM, + ChainId.ARBITRUM, + ChainId.OPTIMISM, + ChainId.BASE, + ChainId.POLYGON, + ChainId.AVALANCHE, + ChainId.BSC, + ChainId.LINEA, + ChainId.ARBITRUM_NOVA, + ChainId.GNOSIS, + ChainId.FANTOM, + ChainId.BTTC, + ChainId.CELO, + ChainId.FILECOIN, + ChainId.HAQQ, + ChainId.KAVA, + ChainId.METIS, + ChainId.THUNDERCORE, + ChainId.SCROLL, + ChainId.ZETACHAIN, + ChainId.MOONBEAM, + ChainId.MOONRIVER, + ChainId.POLYGON_ZKEVM, + ChainId.FUSE, + ChainId.HARMONY, + ChainId.TELOS, + ChainId.BOBA, + ChainId.BOBA_BNB, + ChainId.CORE, + ChainId.CRONOS, + ChainId.BLAST, + ChainId.SKALE_EUROPA, + ChainId.ROOTSTOCK, +] as const + +export type TokenChomperChainId = (typeof TOKEN_CHOMPER_CHAIN_IDS)[number] + +export const TOKEN_CHOMPER_ADDRESS: Record = + { + [ChainId.ETHEREUM]: '0xca226bd9c754F1283123d32B2a7cF62a722f8ADa', + [ChainId.ARBITRUM]: '0xca226bd9c754F1283123d32B2a7cF62a722f8ADa', + [ChainId.OPTIMISM]: '0xca226bd9c754F1283123d32B2a7cF62a722f8ADa', + [ChainId.BASE]: '0xca226bd9c754F1283123d32B2a7cF62a722f8ADa', + [ChainId.POLYGON]: '0xca226bd9c754F1283123d32B2a7cF62a722f8ADa', + [ChainId.AVALANCHE]: '0xca226bd9c754F1283123d32B2a7cF62a722f8ADa', + [ChainId.BSC]: '0xca226bd9c754F1283123d32B2a7cF62a722f8ADa', + [ChainId.LINEA]: '0xca226bd9c754F1283123d32B2a7cF62a722f8ADa', + [ChainId.ARBITRUM_NOVA]: '0xca226bd9c754F1283123d32B2a7cF62a722f8ADa', + [ChainId.GNOSIS]: '0xca226bd9c754F1283123d32B2a7cF62a722f8ADa', + [ChainId.FANTOM]: '0xca226bd9c754F1283123d32B2a7cF62a722f8ADa', + [ChainId.BTTC]: '0xca226bd9c754F1283123d32B2a7cF62a722f8ADa', + [ChainId.CELO]: '0xca226bd9c754F1283123d32B2a7cF62a722f8ADa', + [ChainId.FILECOIN]: '0xca226bd9c754F1283123d32B2a7cF62a722f8ADa', + [ChainId.HAQQ]: '0xca226bd9c754F1283123d32B2a7cF62a722f8ADa', + [ChainId.KAVA]: '0xca226bd9c754F1283123d32B2a7cF62a722f8ADa', + [ChainId.METIS]: '0xca226bd9c754F1283123d32B2a7cF62a722f8ADa', + [ChainId.THUNDERCORE]: '0xca226bd9c754F1283123d32B2a7cF62a722f8ADa', + [ChainId.SCROLL]: '0xca226bd9c754F1283123d32B2a7cF62a722f8ADa', + [ChainId.ZETACHAIN]: '0xca226bd9c754F1283123d32B2a7cF62a722f8ADa', + [ChainId.MOONBEAM]: '0xca226bd9c754F1283123d32B2a7cF62a722f8ADa', + [ChainId.MOONRIVER]: '0xca226bd9c754F1283123d32B2a7cF62a722f8ADa', + [ChainId.POLYGON_ZKEVM]: '0xca226bd9c754F1283123d32B2a7cF62a722f8ADa', + [ChainId.FUSE]: '0xca226bd9c754F1283123d32B2a7cF62a722f8ADa', + [ChainId.HARMONY]: '0xca226bd9c754F1283123d32B2a7cF62a722f8ADa', + [ChainId.TELOS]: '0xca226bd9c754F1283123d32B2a7cF62a722f8ADa', + [ChainId.BOBA]: '0xca226bd9c754F1283123d32B2a7cF62a722f8ADa', + [ChainId.BOBA_BNB]: '0xca226bd9c754F1283123d32B2a7cF62a722f8ADa', + [ChainId.CORE]: '0xca226bd9c754F1283123d32B2a7cF62a722f8ADa', + [ChainId.CRONOS]: '0xca226bd9c754F1283123d32B2a7cF62a722f8ADa', + [ChainId.BLAST]: '0xca226bd9c754F1283123d32B2a7cF62a722f8ADa', + [ChainId.SKALE_EUROPA]: '0xca226bd9c754F1283123d32B2a7cF62a722f8ADa', + [ChainId.ROOTSTOCK]: '0xca226bd9c754F1283123d32B2a7cF62a722f8ADa', + } as const + +export const isTokenChomperChainId = ( + chainId: ChainId, +): chainId is TokenChomperChainId => + TOKEN_CHOMPER_CHAIN_IDS.includes(chainId as TokenChomperChainId) From 33703513752ca75b509bb4172458d4d46d972bf5 Mon Sep 17 00:00:00 2001 From: 0xMasayoshi <0xMasayoshi@protonmail.com> Date: Thu, 8 Aug 2024 09:10:21 +0700 Subject: [PATCH 098/125] chore: add RP5 cronos deployment files --- .../deployments/cronos/RouteProcessor5.json | 704 ++++++++++++++++++ .../9252879aaeb02fabe759ce8768addec4.json | 98 +++ 2 files changed, 802 insertions(+) create mode 100644 protocols/route-processor/deployments/cronos/RouteProcessor5.json create mode 100644 protocols/route-processor/deployments/cronos/solcInputs/9252879aaeb02fabe759ce8768addec4.json diff --git a/protocols/route-processor/deployments/cronos/RouteProcessor5.json b/protocols/route-processor/deployments/cronos/RouteProcessor5.json new file mode 100644 index 0000000000..3a82abe84a --- /dev/null +++ b/protocols/route-processor/deployments/cronos/RouteProcessor5.json @@ -0,0 +1,704 @@ +{ + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_bentoBox", + "type": "address" + }, + { + "internalType": "address[]", + "name": "priviledgedUserList", + "type": "address[]" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "MinimalOutputBalanceViolation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "name": "Route", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "algebraSwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "bentoBox", + "outputs": [ + { + "internalType": "contract IBentoBoxMinimal", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "pancakeV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "priviledgedUsers", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueInput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "processRouteWithTransferValueOutput", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resume", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "bool", + "name": "priviledge", + "type": "bool" + } + ], + "name": "setPriviledge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "transferValueTo", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountValueTransfer", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountOutMin", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "bytes", + "name": "route", + "type": "bytes" + } + ], + "name": "transferValueAndprocessRoute", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "int256", + "name": "amount0Delta", + "type": "int256" + }, + { + "internalType": "int256", + "name": "amount1Delta", + "type": "int256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uniswapV3SwapCallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x5f8d1f56edd72396a99580eebb17d6a76d43f8a62d4436cc6ad9c62ae89a0976", + "receipt": { + "to": null, + "from": "0x282607716D9B4fDD0B094d5864fac56313f5e665", + "contractAddress": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "transactionIndex": 0, + "gasUsed": "3489875", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000020000000000000000000000000000000000000001000000000000000000000000000000000000000000040000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000020000000000000040000000000000000000000000000000000000000000000000000", + "blockHash": "0xc26f56a5718a14a9621b1c876e7b7c0b71efc7fedd74717275ac5326e104c9e4", + "transactionHash": "0x5f8d1f56edd72396a99580eebb17d6a76d43f8a62d4436cc6ad9c62ae89a0976", + "logs": [ + { + "transactionIndex": 0, + "blockNumber": 15236244, + "transactionHash": "0x5f8d1f56edd72396a99580eebb17d6a76d43f8a62d4436cc6ad9c62ae89a0976", + "address": "0xf2614A233c7C3e7f08b1F887Ba133a13f1eb2c55", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000282607716d9b4fdd0b094d5864fac56313f5e665" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0xc26f56a5718a14a9621b1c876e7b7c0b71efc7fedd74717275ac5326e104c9e4" + } + ], + "blockNumber": 15236244, + "cumulativeGasUsed": "3489875", + "status": 1, + "byzantium": true + }, + "args": [ + "0x0000000000000000000000000000000000000000", + [] + ], + "numDeployments": 1, + "solcInputHash": "9252879aaeb02fabe759ce8768addec4", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_bentoBox\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"priviledgedUserList\",\"type\":\"address[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"MinimalOutputBalanceViolation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"name\":\"Route\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"algebraSwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"bentoBox\",\"outputs\":[{\"internalType\":\"contract IBentoBoxMinimal\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"pancakeV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"priviledgedUsers\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueInput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"processRouteWithTransferValueOutput\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"resume\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"priviledge\",\"type\":\"bool\"}],\"name\":\"setPriviledge\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transferValueTo\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountValueTransfer\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenIn\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountIn\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"tokenOut\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amountOutMin\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"route\",\"type\":\"bytes\"}],\"name\":\"transferValueAndprocessRoute\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"amountOut\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"amount0Delta\",\"type\":\"int256\"},{\"internalType\":\"int256\",\"name\":\"amount1Delta\",\"type\":\"int256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"uniswapV3SwapCallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"author\":\"Ilya Lyalin\",\"kind\":\"dev\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IAlgebraPoolActions#swap call\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the PancakeV3Pool#swap call\"}},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"route\":\"Route to process\",\"to\":\"Where to transfer output tokens\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"params\":{\"amountIn\":\"Amount of the input token\",\"amountOutMin\":\"Minimum amount of the output token\",\"amountValueTransfer\":\"How much value to transfer\",\"tokenIn\":\"Address of the input token\",\"tokenOut\":\"Address of the output token\",\"transferValueTo\":\"Address where the value should be transferred\"},\"returns\":{\"amountOut\":\"Actual amount of the output token\"}},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"details\":\"In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\",\"params\":{\"amount0Delta\":\"The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.\",\"amount1Delta\":\"The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.\",\"data\":\"Any data passed through by the caller via the IUniswapV3PoolActions#swap call\"}}},\"title\":\"A route processor for the Sushi Aggregator\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"algebraSwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\"},\"pancakeV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\"},\"processRoute(address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Processes the route generated off-chain. Has a lock\"},\"processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value of input tokens to and then processes the route\"},\"processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"processes the route and sends amount of output token to \"},\"transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)\":{\"notice\":\"Transfers some value to and then processes the route\"},\"uniswapV3SwapCallback(int256,int256,bytes)\":{\"notice\":\"Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RouteProcessor5.sol\":\"RouteProcessor5\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":10000000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor() {\\n _transferOwnership(_msgSender());\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n _checkOwner();\\n _;\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if the sender is not the owner.\\n */\\n function _checkOwner() internal view virtual {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n _transferOwnership(address(0));\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n _transferOwnership(newOwner);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Internal function without access restriction.\\n */\\n function _transferOwnership(address newOwner) internal virtual {\\n address oldOwner = _owner;\\n _owner = newOwner;\\n emit OwnershipTransferred(oldOwner, newOwner);\\n }\\n}\\n\",\"keccak256\":\"0xa94b34880e3c1b0b931662cb1c09e5dfa6662f31cba80e07c5ee71cd135c9673\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\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 Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @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 `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, 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 `from` to `to` 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 from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.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 function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\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\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\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 * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 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 functionCallWithValue(target, data, 0, \\\"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\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 /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\\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\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/InputStream.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\n/** @notice Simple read stream */\\nlibrary InputStream {\\n\\n /** @notice Creates stream from data\\n * @param data data\\n */\\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\\n assembly {\\n stream := mload(0x40)\\n mstore(0x40, add(stream, 64))\\n mstore(stream, data)\\n let length := mload(data)\\n mstore(add(stream, 32), add(data, length))\\n }\\n }\\n\\n /** @notice Checks if stream is not empty\\n * @param stream stream\\n */\\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\\n uint256 pos;\\n uint256 finish;\\n assembly {\\n pos := mload(stream)\\n finish := mload(add(stream, 32))\\n }\\n return pos < finish;\\n }\\n\\n /** @notice Reads uint8 from the stream\\n * @param stream stream\\n */\\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 1)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint16 from the stream\\n * @param stream stream\\n */\\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 2)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint24 from the stream\\n * @param stream stream\\n */\\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 3)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint32 from the stream\\n * @param stream stream\\n */\\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 4)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads uint256 from the stream\\n * @param stream stream\\n */\\n function readUint(uint256 stream) internal pure returns (uint256 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes32 from the stream\\n * @param stream stream\\n */\\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 32)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads address from the stream\\n * @param stream stream\\n */\\n function readAddress(uint256 stream) internal pure returns (address res) {\\n assembly {\\n let pos := mload(stream)\\n pos := add(pos, 20)\\n res := mload(pos)\\n mstore(stream, pos)\\n }\\n }\\n\\n /** @notice Reads bytes from the stream\\n * @param stream stream\\n */\\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\\n assembly {\\n let pos := mload(stream)\\n res := add(pos, 32)\\n let length := mload(res)\\n mstore(stream, add(res, length))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x24e24bd0e49cbddacbf3b26bcd4bdffac63d11f3259bc05bc93c0835e8ff5300\",\"license\":\"UNLICENSED\"},\"contracts/RouteProcessor5.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '../interfaces/IUniswapV2Pair.sol';\\nimport '../interfaces/IUniswapV3Pool.sol';\\nimport '../interfaces/ITridentCLPool.sol';\\nimport '../interfaces/IBentoBoxMinimal.sol';\\nimport '../interfaces/IPool.sol';\\nimport '../interfaces/IWETH.sol';\\nimport '../interfaces/ICurve.sol';\\nimport './InputStream.sol';\\nimport './Utils.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\\n\\nuint8 constant LOCKED = 2;\\nuint8 constant NOT_LOCKED = 1;\\nuint8 constant PAUSED = 2;\\nuint8 constant NOT_PAUSED = 1;\\n\\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\\nuint160 constant MIN_SQRT_RATIO = 4295128739;\\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\\n\\n/// @title A route processor for the Sushi Aggregator\\n/// @author Ilya Lyalin\\ncontract RouteProcessor5 is Ownable {\\n using SafeERC20 for IERC20;\\n using Utils for IERC20;\\n using Utils for address;\\n using SafeERC20 for IERC20Permit;\\n using InputStream for uint256;\\n\\n event Route(\\n address indexed from, \\n address to, \\n address indexed tokenIn, \\n address indexed tokenOut, \\n uint256 amountIn, \\n uint256 amountOutMin,\\n uint256 amountOut\\n );\\n\\n error MinimalOutputBalanceViolation(uint256 amountOut);\\n\\n IBentoBoxMinimal public immutable bentoBox;\\n mapping (address => bool) public priviledgedUsers;\\n address private lastCalledPool;\\n\\n uint8 private unlocked = NOT_LOCKED;\\n uint8 private paused = NOT_PAUSED;\\n modifier lock() {\\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\\n unlocked = LOCKED;\\n _;\\n unlocked = NOT_LOCKED;\\n }\\n\\n modifier onlyOwnerOrPriviledgedUser() {\\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \\\"RP: caller is not the owner or a privileged user\\\");\\n _;\\n }\\n\\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\\n bentoBox = IBentoBoxMinimal(_bentoBox);\\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n\\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\\n priviledgedUsers[priviledgedUserList[i]] = true;\\n }\\n }\\n\\n function setPriviledge(address user, bool priviledge) external onlyOwner {\\n priviledgedUsers[user] = priviledge;\\n }\\n\\n function pause() external onlyOwnerOrPriviledgedUser {\\n paused = PAUSED;\\n }\\n\\n function resume() external onlyOwnerOrPriviledgedUser {\\n paused = NOT_PAUSED;\\n }\\n\\n /// @notice For native unwrapping\\n receive() external payable {}\\n\\n /// @notice Processes the route generated off-chain. Has a lock\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @param to Where to transfer output tokens\\n /// @param route Route to process\\n /// @return amountOut Actual amount of the output token\\n function processRoute(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function transferValueAndprocessRoute(\\n address transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n transferValueTo.transferNative(amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n\\n /// @notice Transfers some value of input tokens to and then processes the route\\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueInput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\\n }\\n \\n /// @notice processes the route and sends amount of output token to \\n /// @param transferValueTo Address where the value should be transferred\\n /// @param amountValueTransfer How much value to transfer\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteWithTransferValueOutput(\\n address payable transferValueTo,\\n uint256 amountValueTransfer,\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) external payable lock returns (uint256 amountOut) {\\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\\n }\\n\\n /// @notice Processes the route generated off-chain\\n /// @param tokenIn Address of the input token\\n /// @param amountIn Amount of the input token\\n /// @param tokenOut Address of the output token\\n /// @param amountOutMin Minimum amount of the output token\\n /// @return amountOut Actual amount of the output token\\n function processRouteInternal(\\n address tokenIn,\\n uint256 amountIn,\\n address tokenOut,\\n uint256 amountOutMin,\\n address to,\\n bytes memory route\\n ) private returns (uint256 amountOut) {\\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\\n\\n uint256 realAmountIn = amountIn;\\n {\\n uint256 step = 0;\\n uint256 stream = InputStream.createStream(route);\\n while (stream.isNotEmpty()) {\\n uint8 commandCode = stream.readUint8();\\n if (commandCode == 1) {\\n uint256 usedAmount = processMyERC20(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 2) processUserERC20(stream, amountIn);\\n else if (commandCode == 3) {\\n uint256 usedAmount = processNative(stream); \\n if (step == 0) realAmountIn = usedAmount;\\n } \\n else if (commandCode == 4) processOnePool(stream);\\n else if (commandCode == 5) processInsideBento(stream);\\n else if (commandCode == 6) applyPermit(tokenIn, stream);\\n else revert('RouteProcessor: Unknown command code');\\n ++step;\\n }\\n }\\n\\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\\n if (tokenIn != Utils.NATIVE_ADDRESS)\\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\\n \\n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\\n\\n amountOut = balanceOutFinal - balanceOutInitial;\\n\\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\\n }\\n\\n /// @notice Applies ERC-2612 permit\\n /// @param tokenIn permitted token\\n /// @param stream Streamed program\\n function applyPermit(address tokenIn, uint256 stream) private {\\n uint256 value = stream.readUint();\\n uint256 deadline = stream.readUint();\\n uint8 v = stream.readUint8();\\n bytes32 r = stream.readBytes32();\\n bytes32 s = stream.readBytes32();\\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\\n }\\n }\\n\\n /// @notice Processes native coin: call swap for all pools that swap from native coin\\n /// @param stream Streamed program\\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\\n amountTotal = address(this).balance;\\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token from this contract balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\\n address token = stream.readAddress();\\n amountTotal = IERC20(token).balanceOf(address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n \\n /// @notice Processes ERC20 token from msg.sender balance:\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n /// @param amountTotal Amount of tokens to take from msg.sender\\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\\n address token = stream.readAddress();\\n distributeAndSwap(stream, msg.sender, token, amountTotal);\\n }\\n\\n /// @notice Processes ERC20 token for cases when the token has only one output pool\\n /// @notice In this case liquidity is already at pool balance. This is an optimization\\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processOnePool(uint256 stream) private {\\n address token = stream.readAddress();\\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\\n }\\n\\n /// @notice Processes Bento tokens \\n /// @notice Call swap for all pools that swap from this token\\n /// @param stream Streamed program\\n function processInsideBento(uint256 stream) private {\\n address token = stream.readAddress();\\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\\n unchecked {\\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\\n }\\n distributeAndSwap(stream, address(this), token, amountTotal);\\n }\\n\\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountTotal Total amount of tokenIn for swaps \\n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\\n uint8 num = stream.readUint8();\\n unchecked {\\n for (uint256 i = 0; i < num; ++i) {\\n uint16 share = stream.readUint16();\\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\\n amountTotal -= amount;\\n swap(stream, from, tokenIn, amount);\\n }\\n }\\n }\\n\\n /// @notice Makes swap\\n /// @param stream Streamed program\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 poolType = stream.readUint8();\\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\\n else revert('RouteProcessor: Unknown pool type');\\n }\\n\\n /// @notice Wraps/unwraps native token\\n /// @param stream [direction & fake, recipient, wrapToken?]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 directionAndFake = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (directionAndFake & 1 == 1) { // wrap native\\n address wrapToken = stream.readAddress();\\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\\n } else { // unwrap native\\n if (directionAndFake & 2 == 0) {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IWETH(tokenIn).withdraw(amountIn);\\n }\\n to.transferNative(amountIn);\\n }\\n }\\n\\n /// @notice Bridge/unbridge tokens to/from Bento\\n /// @param stream [direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n\\n if (direction > 0) { // outside to Bento\\n // deposit to arbitrary recipient is possible only from address(bentoBox)\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\\n else {\\n // tokens already are at address(bentoBox)\\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\\n bentoBox.strategyData(tokenIn).balance -\\n bentoBox.totals(tokenIn).elastic;\\n }\\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\\n } else { // Bento to outside\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\\n }\\n }\\n\\n /// @notice UniswapV2 pool swap\\n /// @param stream [pool, direction, recipient, fee]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 direction = stream.readUint8();\\n address to = stream.readAddress();\\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\\n\\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\\n\\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\\n\\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\\n }\\n\\n /// @notice Trident pool swap\\n /// @param stream [pool, swapData]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bytes memory swapData = stream.readBytes();\\n\\n if (from != INTERNAL_INPUT_SOURCE) {\\n bentoBox.transfer(tokenIn, from, pool, amountIn);\\n }\\n \\n IPool(pool).swap(swapData);\\n }\\n\\n /// @notice UniswapV3 pool swap\\n /// @param stream [pool, direction, recipient]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n bool zeroForOne = stream.readUint8() > 0;\\n address recipient = stream.readAddress();\\n\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\\n\\n lastCalledPool = pool;\\n IUniswapV3Pool(pool).swap(\\n recipient,\\n zeroForOne,\\n int256(amountIn),\\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\\n abi.encode(tokenIn)\\n );\\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\\n function uniswapV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) public {\\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\\n \\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\\n (address tokenIn) = abi.decode(data, (address));\\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\\n function algebraSwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\\n function pancakeV3SwapCallback(\\n int256 amount0Delta,\\n int256 amount1Delta,\\n bytes calldata data\\n ) external {\\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\\n }\\n\\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\\n /// @param from Where to take liquidity for swap\\n /// @param tokenIn Input token\\n /// @param amountIn Amount of tokenIn to take for swap\\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\\n address pool = stream.readAddress();\\n uint8 poolType = stream.readUint8();\\n int128 fromIndex = int8(stream.readUint8());\\n int128 toIndex = int8(stream.readUint8());\\n address to = stream.readAddress();\\n address tokenOut = stream.readAddress();\\n\\n uint256 amountOut;\\n if (tokenIn == Utils.NATIVE_ADDRESS) {\\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\\n } else {\\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\\n IERC20(tokenIn).approveSafe(pool, amountIn);\\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n else {\\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\\n amountOut = balanceAfter - balanceBefore;\\n }\\n }\\n\\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\\n }\\n}\\n\",\"keccak256\":\"0xcd53a7f473f1847d44c42777a194203cbff02b8c761cb2935402401f57c918a2\",\"license\":\"UNLICENSED\"},\"contracts/Utils.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity 0.8.10;\\n\\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\\n\\nlibrary Utils {\\n using SafeERC20 for IERC20;\\n\\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\\n\\n /**\\n * @dev returns user's balance of token (or native)\\n */\\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\\n if (token == NATIVE_ADDRESS) return address(user).balance;\\n else return IERC20(token).balanceOf(user);\\n }\\n\\n /**\\n * @dev transfers native with correct revert bubble up\\n */\\n function transferNative(address to, uint256 amount) internal {\\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\\n if (!success) {\\n assembly {\\n revert(add(32, returnBytes), mload(returnBytes))\\n }\\n }\\n }\\n\\n /**\\n * @dev transfers ERC20 or native\\n */\\n function transferAny(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\\n else IERC20(token).safeTransfer(to, amount);\\n }\\n\\n /**\\n * @dev transfers from ERC20 or transfers native\\n */\\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n (bool success, bytes memory data) = address(token).call(\\n abi.encodeWithSelector(token.approve.selector, spender, amount)\\n );\\n return success && (data.length == 0 || abi.decode(data, (bool)));\\n }\\n\\n /**\\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \\n * current allowance are not zero simultaniously (USDT for example). \\n * In second case it tries to set allowance to 0, and then back to amount.\\n * @param token The token targeted by the call.\\n * @param spender token spender\\n * @param amount token amount\\n */\\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\\n return approveStable(token, spender, amount) \\n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\\n }\\n}\\n\",\"keccak256\":\"0x8c8439edc00b403abd3f34be75a06b1fe71152644ae9f19488af596bbc534ffe\",\"license\":\"UNLICENSED\"},\"interfaces/IBentoBoxMinimal.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\nstruct Rebase {\\n uint128 elastic;\\n uint128 base;\\n}\\n\\nstruct StrategyData {\\n uint64 strategyStartDate;\\n uint64 targetPercentage;\\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\\n}\\n\\n/// @notice A rebasing library\\nlibrary RebaseLibrary {\\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\\n if (total.elastic == 0) {\\n base = elastic;\\n } else {\\n base = (elastic * total.base) / total.elastic;\\n }\\n }\\n\\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\\n if (total.base == 0) {\\n elastic = base;\\n } else {\\n elastic = (base * total.elastic) / total.base;\\n }\\n }\\n}\\n\\n/// @notice Minimal BentoBox vault interface.\\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\\ninterface IBentoBoxMinimal {\\n /// @notice Balance per ERC-20 token per account in shares.\\n function balanceOf(address, address) external view returns (uint256);\\n\\n /// @dev Helper function to represent an `amount` of `token` in shares.\\n /// @param token The ERC-20 token.\\n /// @param amount The `token` amount.\\n /// @param roundUp If the result `share` should be rounded up.\\n /// @return share The token amount represented in shares.\\n function toShare(\\n address token,\\n uint256 amount,\\n bool roundUp\\n ) external view returns (uint256 share);\\n\\n /// @dev Helper function to represent shares back into the `token` amount.\\n /// @param token The ERC-20 token.\\n /// @param share The amount of shares.\\n /// @param roundUp If the result should be rounded up.\\n /// @return amount The share amount back into native representation.\\n function toAmount(\\n address token,\\n uint256 share,\\n bool roundUp\\n ) external view returns (uint256 amount);\\n\\n /// @notice Registers this contract so that users can approve it for BentoBox.\\n function registerProtocol() external;\\n\\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\\n /// @param token The ERC-20 token to deposit.\\n /// @param from which account to pull the tokens.\\n /// @param to which account to push the tokens.\\n /// @param amount Token amount in native representation to deposit.\\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\\n /// @return amountOut The amount deposited.\\n /// @return shareOut The deposited amount represented in shares.\\n function deposit(\\n address token,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external payable returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Withdraws an amount of `token` from a user account.\\n /// @param token_ The ERC-20 token to withdraw.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\\n /// @param share Like above, but `share` takes precedence over `amount`.\\n function withdraw(\\n address token_,\\n address from,\\n address to,\\n uint256 amount,\\n uint256 share\\n ) external returns (uint256 amountOut, uint256 shareOut);\\n\\n /// @notice Transfer shares from a user account to another one.\\n /// @param token The ERC-20 token to transfer.\\n /// @param from which user to pull the tokens.\\n /// @param to which user to push the tokens.\\n /// @param share The amount of `token` in shares.\\n function transfer(\\n address token,\\n address from,\\n address to,\\n uint256 share\\n ) external;\\n\\n /// @dev Reads the Rebase `totals`from storage for a given token\\n function totals(address token) external view returns (Rebase memory total);\\n\\n function strategyData(address token) external view returns (StrategyData memory total);\\n\\n /// @dev Approves users' BentoBox assets to a \\\"master\\\" contract.\\n function setMasterContractApproval(\\n address user,\\n address masterContract,\\n bool approved,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n function harvest(\\n address token,\\n bool balance,\\n uint256 maxChangeAmount\\n ) external;\\n}\\n\",\"keccak256\":\"0x0c12eba7a5b9d22d37ab8883fe22d6a312a90682809dbd11c43f8e6ceaff73bf\",\"license\":\"UNLICENSED\"},\"interfaces/ICurve.sol\":{\"content\":\"// SPDX-License-Identifier: UNLICENSED\\n\\npragma solidity >=0.8.0;\\n\\ninterface ICurve {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\\n}\\n\\ninterface ICurveLegacy {\\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\\n}\\n\\n\",\"keccak256\":\"0x3d4940b3583e06dde20f12e92d2f6ac573b3f64bdaa1e8f480656a3763852518\",\"license\":\"UNLICENSED\"},\"interfaces/IPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity >=0.5.0;\\npragma experimental ABIEncoderV2;\\n\\n/// @notice Trident pool interface.\\ninterface IPool {\\n /// @notice Executes a swap from one token to another.\\n /// @dev The input tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Executes a swap from one token to another with a callback.\\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\\n\\n /// @notice Mints liquidity tokens.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\\n function mint(bytes calldata data) external returns (uint256 liquidity);\\n\\n /// @notice Burns liquidity tokens.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\\n\\n /// @notice Burns liquidity tokens for a single output token.\\n /// @dev The input LP tokens must've already been sent to the pool.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return amountOut The amount of output tokens that were sent to the user.\\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\\n\\n /// @return A unique identifier for the pool type.\\n function poolIdentifier() external pure returns (bytes32);\\n\\n /// @return An array of tokens supported by the pool.\\n function getAssets() external view returns (address[] memory);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\\n\\n /// @notice Simulates a trade and returns the expected output.\\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\\n /// @param data ABI-encoded params that the pool requires.\\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\\n\\n /// @dev This event must be emitted on all swaps.\\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\\n\\n /// @dev This struct frames output tokens for burns.\\n struct TokenAmount {\\n address token;\\n uint256 amount;\\n }\\n}\\n\",\"keccak256\":\"0xa6f92ccb525b018c0c209819640e8d746f1134b4c4d9acd4f22d3e170323f1fa\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/ITridentCLPool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface ITridentCLPool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bool unwrapBento,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x572376b80c86a94692b0e27e6e63790b763295e32ba1f956c1d331fc1296de8d\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IUniswapV2Pair.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity >=0.5.0;\\n\\ninterface IUniswapV2Pair {\\n event Approval(address indexed owner, address indexed spender, uint value);\\n event Transfer(address indexed from, address indexed to, uint value);\\n\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint);\\n function balanceOf(address owner) external view returns (uint);\\n function allowance(address owner, address spender) external view returns (uint);\\n\\n function approve(address spender, uint value) external returns (bool);\\n function transfer(address to, uint value) external returns (bool);\\n function transferFrom(address from, address to, uint value) external returns (bool);\\n\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n function nonces(address owner) external view returns (uint);\\n\\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\\n\\n event Mint(address indexed sender, uint amount0, uint amount1);\\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\\n event Swap(\\n address indexed sender,\\n uint amount0In,\\n uint amount1In,\\n uint amount0Out,\\n uint amount1Out,\\n address indexed to\\n );\\n event Sync(uint112 reserve0, uint112 reserve1);\\n\\n function MINIMUM_LIQUIDITY() external pure returns (uint);\\n function factory() external view returns (address);\\n function token0() external view returns (address);\\n function token1() external view returns (address);\\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\\n function price0CumulativeLast() external view returns (uint);\\n function price1CumulativeLast() external view returns (uint);\\n function kLast() external view returns (uint);\\n\\n function mint(address to) external returns (uint liquidity);\\n function burn(address to) external returns (uint amount0, uint amount1);\\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\\n function skim(address to) external;\\n function sync() external;\\n\\n function initialize(address, address) external;\\n}\",\"keccak256\":\"0x08f9a63b34855eec941be8d36a04424f1a1725a2c030373fcef3afeb480ca385\",\"license\":\"GPL-3.0\"},\"interfaces/IUniswapV3Pool.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IUniswapV3Pool {\\n function token0() external returns (address);\\n function token1() external returns (address);\\n\\n function swap(\\n address recipient,\\n bool zeroForOne,\\n int256 amountSpecified,\\n uint160 sqrtPriceLimitX96,\\n bytes calldata data\\n ) external returns (int256 amount0, int256 amount1);\\n}\\n\",\"keccak256\":\"0x2a4d7c6120e613f0e95d4dc8c650efb9b59e3c25c64e3e5c0a379281500f0a79\",\"license\":\"GPL-3.0-or-later\"},\"interfaces/IWETH.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0-or-later\\n\\npragma solidity 0.8.10;\\n\\ninterface IWETH {\\n function deposit() external payable;\\n\\n function transfer(address to, uint256 value) external returns (bool);\\n\\n function withdraw(uint256) external;\\n}\\n\",\"keccak256\":\"0xae8529ae159f784b90fdcd0629bd03bf7b68accc81edccac53357ad08406a378\",\"license\":\"GPL-3.0-or-later\"}},\"version\":1}", + "bytecode": "0x60a06040526002805461ffff60a01b191661010160a01b1790553480156200002657600080fd5b50604051620040a3380380620040a383398101604081905262000049916200016e565b6200005433620000eb565b6001600160a01b038216608052600280546001600160a01b031916600117905560005b8151811015620000e25760018060008484815181106200009b576200009b62000257565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000d9816200026d565b91505062000077565b50505062000297565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200015357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200018257600080fd5b6200018d836200013b565b602084810151919350906001600160401b0380821115620001ad57600080fd5b818601915086601f830112620001c257600080fd5b815181811115620001d757620001d762000158565b8060051b604051601f19603f83011681018181108582111715620001ff57620001ff62000158565b6040529182528482019250838101850191898311156200021e57600080fd5b938501935b82851015620002475762000237856200013b565b8452938501939285019262000223565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200029057634e487b7160e01b600052601160045260246000fd5b5060010190565b608051613da3620003006000396000818161018d01528181611798015281816127380152818161279d01528181612807015281816128cc0152818161297901528181612a5d01528181612b6401528181612c1001528181612cdf0152612df10152613da36000f3fe6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "deployedBytecode": "0x6080604052600436106100ec5760003560e01c8063715018a61161008a5780639a1f3406116100595780639a1f34061461023c578063cd0fb7a71461025c578063f2fde38b1461029c578063fa461e33146102bc57600080fd5b8063715018a6146101d45780638456cb59146101e95780638da5cb5b146101fe57806393b3774c1461022957600080fd5b80632c8958f6116100c65780632c8958f61461010f57806347f8bd41146101555780636678ec1f146101685780636b2ace871461017b57600080fd5b8063046f7da2146100f857806323a69e751461010f5780632646478b1461012f57600080fd5b366100f357005b600080fd5b34801561010457600080fd5b5061010d6102dc565b005b34801561011b57600080fd5b5061010d61012a3660046135d4565b6103e4565b61014261013d366004613750565b6103f6565b6040519081526020015b60405180910390f35b6101426101633660046137d7565b6105a0565b6101426101763660046137d7565b61076e565b34801561018757600080fd5b506101af7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161014c565b3480156101e057600080fd5b5061010d61091c565b3480156101f557600080fd5b5061010d610930565b34801561020a57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101af565b6101426102373660046137d7565b610a33565b34801561024857600080fd5b5061010d61025736600461388a565b610ba4565b34801561026857600080fd5b5061028c6102773660046138c3565b60016020526000908152604090205460ff1681565b604051901515815260200161014c565b3480156102a857600080fd5b5061010d6102b73660046138c3565b610c02565b3480156102c857600080fd5b5061010d6102d73660046135d4565b610cb9565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061031157503360009081526001602052604090205460ff165b6103a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c6567656420757365720000000000000000000000000000000060648201526084015b60405180910390fd5b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055565b6103f084848484610cb9565b50505050565b60025460009074010000000000000000000000000000000000000000900460ff16600114610480576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610508576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1674020000000000000000000000000000000000000000179055610555878787878787610e67565b9050600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790559695505050505050565b60025460009074010000000000000000000000000000000000000000900460ff1660011461062a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff166001146106b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff88168a8a61121d565b610720878787878787610e67565b90505b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905598975050505050505050565b60025460009074010000000000000000000000000000000000000000900460ff166001146107f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610880576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740200000000000000000000000000000000000000001790556108cd878787873087610e67565b90506108f073ffffffffffffffffffffffffffffffffffffffff86168a8a611280565b610723836108fe8a84613916565b73ffffffffffffffffffffffffffffffffffffffff88169190611280565b6109246112dd565b61092e600061135e565b565b60005473ffffffffffffffffffffffffffffffffffffffff1633148061096557503360009081526001602052604090205460ff165b6109f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f52503a2063616c6c6572206973206e6f7420746865206f776e6572206f72206160448201527f2070726976696c656765642075736572000000000000000000000000000000006064820152608401610399565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167502000000000000000000000000000000000000000000179055565b60025460009074010000000000000000000000000000000000000000900460ff16600114610abd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f72206973206c6f636b656400000000000000006044820152606401610399565b6002547501000000000000000000000000000000000000000000900460ff16600114610b45576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f526f75746550726f636573736f722069732070617573656400000000000000006044820152606401610399565b600280547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167402000000000000000000000000000000000000000017905561071273ffffffffffffffffffffffffffffffffffffffff8a16896113d3565b610bac6112dd565b73ffffffffffffffffffffffffffffffffffffffff91909116600090815260016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b610c0a6112dd565b73ffffffffffffffffffffffffffffffffffffffff8116610cad576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610399565b610cb68161135e565b50565b60025473ffffffffffffffffffffffffffffffffffffffff163314610d60576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603e60248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a2063616c6c2066726f6d20756e6b6e6f776e20736f7572636500006064820152608401610399565b6000808513610d6f5783610d71565b845b905060008113610e03576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603960248201527f526f75746550726f636573736f722e756e697377617056335377617043616c6c60448201527f6261636b3a206e6f7420706f73697469766520616d6f756e74000000000000006064820152608401610399565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001660011790556000610e3c838501856138c3565b9050610e5f73ffffffffffffffffffffffffffffffffffffffff82163384611445565b505050505050565b600080610e8a73ffffffffffffffffffffffffffffffffffffffff891633611519565b90506000610eae73ffffffffffffffffffffffffffffffffffffffff881686611519565b905087600080610ed287604080518082019091528181528151909101602082015290565b90505b805160208201511115611028576000610ef48280516001018051915290565b90508060ff1660011415610f1e576000610f0d83611604565b905083610f18578094505b50611017565b8060ff1660021415610f3957610f34828d6116c9565b611017565b8060ff1660031415610f50576000610f0d836116e9565b8060ff1660041415610f6557610f348261170f565b8060ff1660051415610f7a57610f3482611735565b8060ff1660061415610f9057610f348d8361183a565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f723a20556e6b6e6f776e20636f6d6d616e642060448201527f636f6465000000000000000000000000000000000000000000000000000000006064820152608401610399565b6110208361392d565b925050610ed5565b506000905061104d73ffffffffffffffffffffffffffffffffffffffff8c1633611519565b905073ffffffffffffffffffffffffffffffffffffffff8b1673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611124578361108b8b83613966565b61109690600a613966565b1015611124576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602f60248201527f526f75746550726f636573736f723a204d696e696d616c20696e70757420626160448201527f6c616e63652076696f6c6174696f6e00000000000000000000000000000000006064820152608401610399565b600061114673ffffffffffffffffffffffffffffffffffffffff8b1689611519565b90506111528985613966565b811015611198576111638482613916565b6040517f963b34a500000000000000000000000000000000000000000000000000000000815260040161039991815260200190565b6111a28482613916565b6040805173ffffffffffffffffffffffffffffffffffffffff8b81168252602082018790529181018c905260608101839052919750808c1691908e169033907f2db5ddd0b42bdbca0d69ea16f234a870a485854ae0d91f16643d6f317d8b89949060800160405180910390a450505050509695505050505050565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561125e5761125982826113d3565b505050565b61125973ffffffffffffffffffffffffffffffffffffffff841633848461196a565b73ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14156112bc5761125982826113d3565b61125973ffffffffffffffffffffffffffffffffffffffff84168383611445565b60005473ffffffffffffffffffffffffffffffffffffffff16331461092e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610399565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d806000811461142e576040519150601f19603f3d011682016040523d82523d6000602084013e611433565b606091505b5091509150816103f057805181602001fd5b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526112599084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091526119c8565b600073ffffffffffffffffffffffffffffffffffffffff831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee141561156b575073ffffffffffffffffffffffffffffffffffffffff8116316115fe565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb919061397e565b90505b92915050565b6000806116178380516014018051915290565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015611684573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116a8919061397e565b915081156116b7576001820391505b6116c383308385611ad4565b50919050565b60006116db8380516014018051915290565b905061125983338385611ad4565b4761170a823073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee84611ad4565b919050565b60006117218280516014018051915290565b9050611731826000836000611b2f565b5050565b60006117478280516014018051915290565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff80831660048301523060248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa1580156117df573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611803919061397e565b9050801561182e577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff015b61125983308484611ad4565b600061184c8280516020018051915290565b905060006118608380516020018051915290565b905060006118748480516001018051915290565b905060006118888580516020018051915290565b9050600061189c8680516020018051915290565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152909150859073ffffffffffffffffffffffffffffffffffffffff89169063dd62ed3e90604401602060405180830381865afa158015611911573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611935919061397e565b10156119615761196173ffffffffffffffffffffffffffffffffffffffff881633308888888888611c63565b50505050505050565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526103f09085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401611497565b6000611a2a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611ee39092919063ffffffff16565b8051909150156112595780806020019051810190611a489190613997565b611259576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610399565b6000611ae68580516001018051915290565b905060005b8160ff16811015610e5f576000611b088780516002018051915290565b61ffff8082168602049485900394909150611b2588888884611b2f565b5050600101611aeb565b6000611b418580516001018051915290565b905060ff8116611b5c57611b5785858585611efa565b611c5c565b8060ff1660011415611b7457611b57858585856122af565b8060ff1660021415611b8c57611b57858585856124ef565b8060ff1660031415611ba457611b57858585856126cd565b8060ff1660041415611bbc57611b5785858585612d55565b8060ff1660051415611bd457611b5785858585612ee3565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f526f75746550726f636573736f723a20556e6b6e6f776e20706f6f6c2074797060448201527f65000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b5050505050565b6040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8881166004830152600091908a1690637ecebe0090602401602060405180830381865afa158015611cd3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf7919061397e565b6040517fd505accf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a811660048301528981166024830152604482018990526064820188905260ff8716608483015260a4820186905260c48201859052919250908a169063d505accf9060e401600060405180830381600087803b158015611d9157600080fd5b505af1158015611da5573d6000803e3d6000fd5b50506040517f7ecebe0000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b81166004830152600093508c169150637ecebe0090602401602060405180830381865afa158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c919061397e565b9050611e49826001613966565b8114611ed7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f5361666545524332303a207065726d697420646964206e6f742073756363656560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610399565b50505050505050505050565b6060611ef2848460008561329a565b949350505050565b6000611f0c8580516014018051915290565b90506000611f208680516001018051915290565b90506000611f348780516014018051915290565b90506000611f488880516003018051915290565b905073ffffffffffffffffffffffffffffffffffffffff8716301415611f8e57611f8973ffffffffffffffffffffffffffffffffffffffff87168587611445565b611fce565b73ffffffffffffffffffffffffffffffffffffffff8716331415611fce57611fce73ffffffffffffffffffffffffffffffffffffffff871633868861196a565b6000808573ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561201c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061204091906139d2565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff1691506000821180156120755750600081115b6120db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f57726f6e6720706f6f6c207265736572766573000000000000000000000000006044820152606401610399565b6000808660ff166001146120f05782846120f3565b83835b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015292945090925083918c16906370a0823190602401602060405180830381865afa158015612167573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218b919061397e565b6121959190613916565b985060006121a686620f4240613a22565b6121b59062ffffff168b613a46565b90506000816121c785620f4240613a46565b6121d19190613966565b6121db8484613a46565b6121e59190613a83565b90506000808a60ff166001146121fd57826000612201565b6000835b604080516000815260208101918290527f022c0d9f00000000000000000000000000000000000000000000000000000000909152919350915073ffffffffffffffffffffffffffffffffffffffff8d169063022c0d9f9061226b90859085908f9060248101613b34565b600060405180830381600087803b15801561228557600080fd5b505af1158015612299573d6000803e3d6000fd5b5050505050505050505050505050505050505050565b60006122c18580516014018051915290565b90506000806122d68780516001018051915290565b60ff1611905060006122ee8780516014018051915290565b905073ffffffffffffffffffffffffffffffffffffffff86163314156123305761233073ffffffffffffffffffffffffffffffffffffffff861633308761196a565b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915563128acb08828487816123a45761239f600173fffd8963efd1fc6a506488495d951d5263988d26613b6f565b6123b4565b6123b46401000276a36001613b9c565b6040805173ffffffffffffffffffffffffffffffffffffffff8d166020820152016040516020818303038152906040526040518663ffffffff1660e01b8152600401612404959493929190613bd4565b60408051808303816000875af1158015612422573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124469190613c1b565b505060025473ffffffffffffffffffffffffffffffffffffffff16600114611961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f526f75746550726f636573736f722e73776170556e6956333a20756e6578706560448201527f63746564000000000000000000000000000000000000000000000000000000006064820152608401610399565b60006125018580516001018051915290565b905060006125158680516014018051915290565b9050600180831614156125e45760006125348780516014018051915290565b9050600283166125a0578073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b15801561258657600080fd5b505af115801561259a573d6000803e3d6000fd5b50505050505b73ffffffffffffffffffffffffffffffffffffffff821630146125de576125de73ffffffffffffffffffffffffffffffffffffffff82168386611445565b50610e5f565b600282166126ad5773ffffffffffffffffffffffffffffffffffffffff851633141561262c5761262c73ffffffffffffffffffffffffffffffffffffffff851633308661196a565b6040517f2e1a7d4d0000000000000000000000000000000000000000000000000000000081526004810184905273ffffffffffffffffffffffffffffffffffffffff851690632e1a7d4d90602401600060405180830381600087803b15801561269457600080fd5b505af11580156126a8573d6000803e3d6000fd5b505050505b610e5f73ffffffffffffffffffffffffffffffffffffffff8216846113d3565b60006126df8580516001018051915290565b905060006126f38680516014018051915290565b905060ff821615612aee5773ffffffffffffffffffffffffffffffffffffffff85163014156127625761275d73ffffffffffffffffffffffffffffffffffffffff85167f000000000000000000000000000000000000000000000000000000000000000085611445565b612a18565b73ffffffffffffffffffffffffffffffffffffffff85163314156127c25761275d73ffffffffffffffffffffffffffffffffffffffff8516337f00000000000000000000000000000000000000000000000000000000000000008661196a565b6040517f4ffe34db00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f00000000000000000000000000000000000000000000000000000000000000001690634ffe34db906024016040805180830381865afa15801561284d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128719190613c5f565b516040517fdf23b45b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526fffffffffffffffffffffffffffffffff909216917f0000000000000000000000000000000000000000000000000000000000000000169063df23b45b90602401606060405180830381865afa158015612913573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129379190613cd2565b60409081015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301526fffffffffffffffffffffffffffffffff909216918716906370a0823190602401602060405180830381865afa1580156129dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a01919061397e565b612a0b9190613966565b612a159190613916565b92505b6040517f02b9446c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301527f000000000000000000000000000000000000000000000000000000000000000081166024830181905290831660448301526064820185905260006084830152906302b9446c9060a40160408051808303816000875af1158015612ac3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae79190613c1b565b5050610e5f565b73ffffffffffffffffffffffffffffffffffffffff851615612bc5576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301528681166024830152306044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612ba857600080fd5b505af1158015612bbc573d6000803e3d6000fd5b50505050612c7e565b6040517ff7888aec00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301523060248301527f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90604401602060405180830381865afa158015612c57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c7b919061397e565b92505b6040517f97da6d3000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152306024830152828116604483015260006064830152608482018590527f000000000000000000000000000000000000000000000000000000000000000016906397da6d309060a40160408051808303816000875af1158015612d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d4b9190613c1b565b5050505050505050565b6000612d678580516014018051915290565b85516020808201805190920101875290915073ffffffffffffffffffffffffffffffffffffffff851615612e4e576040517ff18d03cc00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015286811660248301528381166044830152606482018590527f0000000000000000000000000000000000000000000000000000000000000000169063f18d03cc90608401600060405180830381600087803b158015612e3557600080fd5b505af1158015612e49573d6000803e3d6000fd5b505050505b6040517f627dd56a00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063627dd56a90612ea0908490600401613d3e565b6020604051808303816000875af1158015612ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611961919061397e565b6000612ef58580516014018051915290565b90506000612f098680516001018051915290565b90506000612f1d8780516001018051915290565b60000b90506000612f348880516001018051915290565b60000b90506000612f4b8980516014018051915290565b90506000612f5f8a80516014018051915290565b9050600073ffffffffffffffffffffffffffffffffffffffff891673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1415613048576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124908a9060840160206040518083038185885af115801561301c573d6000803e3d6000fd5b50505050506040513d601f19601f82011682018060405250810190613041919061397e565b905061324f565b73ffffffffffffffffffffffffffffffffffffffff8a163314156130885761308873ffffffffffffffffffffffffffffffffffffffff8a1633308b61196a565b6130a973ffffffffffffffffffffffffffffffffffffffff8a16888a6133b3565b5060ff861661315c576040517f3df02124000000000000000000000000000000000000000000000000000000008152600f86810b600483015285900b6024820152604481018990526000606482015273ffffffffffffffffffffffffffffffffffffffff881690633df02124906084016020604051808303816000875af1158015613138573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613041919061397e565b600061317e73ffffffffffffffffffffffffffffffffffffffff841630611519565b6040517f3df02124000000000000000000000000000000000000000000000000000000008152600f88810b600483015287900b6024820152604481018b90526000606482015290915073ffffffffffffffffffffffffffffffffffffffff891690633df0212490608401600060405180830381600087803b15801561320257600080fd5b505af1158015613216573d6000803e3d6000fd5b506000925061323e91505073ffffffffffffffffffffffffffffffffffffffff851630611519565b905061324a8282613916565b925050505b73ffffffffffffffffffffffffffffffffffffffff8316301461328d5761328d73ffffffffffffffffffffffffffffffffffffffff83168483611280565b5050505050505050505050565b60608247101561332c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610399565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516133559190613d51565b60006040518083038185875af1925050503d8060008114613392576040519150601f19603f3d011682016040523d82523d6000602084013e613397565b606091505b50915091506133a8878383876133e4565b979650505050505050565b60006133c0848484613481565b80611ef257506133d284846000613481565b8015611ef25750611ef2848484613481565b606083156134775782516134705773ffffffffffffffffffffffffffffffffffffffff85163b613470576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610399565b5081611ef2565b611ef28383613590565b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839283929188169161351a9190613d51565b6000604051808303816000865af19150503d8060008114613557576040519150601f19603f3d011682016040523d82523d6000602084013e61355c565b606091505b50915091508180156135865750805115806135865750808060200190518101906135869190613997565b9695505050505050565b8151156135a05781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103999190613d3e565b600080600080606085870312156135ea57600080fd5b8435935060208501359250604085013567ffffffffffffffff8082111561361057600080fd5b818701915087601f83011261362457600080fd5b81358181111561363357600080fd5b88602082850101111561364557600080fd5b95989497505060200194505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610cb657600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600082601f8301126136b657600080fd5b813567ffffffffffffffff808211156136d1576136d1613676565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190828211818310171561371757613717613676565b8160405283815286602085880101111561373057600080fd5b836020870160208301376000602085830101528094505050505092915050565b60008060008060008060c0878903121561376957600080fd5b863561377481613654565b955060208701359450604087013561378b81613654565b93506060870135925060808701356137a281613654565b915060a087013567ffffffffffffffff8111156137be57600080fd5b6137ca89828a016136a5565b9150509295509295509295565b600080600080600080600080610100898b0312156137f457600080fd5b88356137ff81613654565b975060208901359650604089013561381681613654565b955060608901359450608089013561382d81613654565b935060a0890135925060c089013561384481613654565b915060e089013567ffffffffffffffff81111561386057600080fd5b61386c8b828c016136a5565b9150509295985092959890939650565b8015158114610cb657600080fd5b6000806040838503121561389d57600080fd5b82356138a881613654565b915060208301356138b88161387c565b809150509250929050565b6000602082840312156138d557600080fd5b81356138e081613654565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613928576139286138e7565b500390565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82141561395f5761395f6138e7565b5060010190565b60008219821115613979576139796138e7565b500190565b60006020828403121561399057600080fd5b5051919050565b6000602082840312156139a957600080fd5b81516138e08161387c565b80516dffffffffffffffffffffffffffff8116811461170a57600080fd5b6000806000606084860312156139e757600080fd5b6139f0846139b4565b92506139fe602085016139b4565b9150604084015163ffffffff81168114613a1757600080fd5b809150509250925092565b600062ffffff83811690831681811015613a3e57613a3e6138e7565b039392505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615613a7e57613a7e6138e7565b500290565b600082613ab9577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60005b83811015613ad9578181015183820152602001613ac1565b838111156103f05750506000910152565b60008151808452613b02816020860160208601613abe565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006135866080830184613aea565b600073ffffffffffffffffffffffffffffffffffffffff83811690831681811015613a3e57613a3e6138e7565b600073ffffffffffffffffffffffffffffffffffffffff808316818516808303821115613bcb57613bcb6138e7565b01949350505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a060808301526133a860a0830184613aea565b60008060408385031215613c2e57600080fd5b505080516020909101519092909150565b80516fffffffffffffffffffffffffffffffff8116811461170a57600080fd5b600060408284031215613c7157600080fd5b6040516040810181811067ffffffffffffffff82111715613c9457613c94613676565b604052613ca083613c3f565b8152613cae60208401613c3f565b60208201529392505050565b805167ffffffffffffffff8116811461170a57600080fd5b600060608284031215613ce457600080fd5b6040516060810181811067ffffffffffffffff82111715613d0757613d07613676565b604052613d1383613cba565b8152613d2160208401613cba565b6020820152613d3260408401613c3f565b60408201529392505050565b6020815260006138e06020830184613aea565b60008251613d63818460208701613abe565b919091019291505056fea26469706673582212209f3b5dd61e1718e28656003bdb1e93579bac1e86bdbff2eb5116c63421166cc164736f6c634300080a0033", + "devdoc": { + "author": "Ilya Lyalin", + "kind": "dev", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IAlgebraPoolActions#swap call" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the PancakeV3Pool#swap call" + } + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "route": "Route to process", + "to": "Where to transfer output tokens", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "params": { + "amountIn": "Amount of the input token", + "amountOutMin": "Minimum amount of the output token", + "amountValueTransfer": "How much value to transfer", + "tokenIn": "Address of the input token", + "tokenOut": "Address of the output token", + "transferValueTo": "Address where the value should be transferred" + }, + "returns": { + "amountOut": "Actual amount of the output token" + } + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "details": "In the implementation you must pay the pool tokens owed for the swap. The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. amount0Delta and amount1Delta can both be 0 if no tokens were swapped.", + "params": { + "amount0Delta": "The amount of token0 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token0 to the pool.", + "amount1Delta": "The amount of token1 that was sent (negative) or must be received (positive) by the pool by the end of the swap. If positive, the callback must send that amount of token1 to the pool.", + "data": "Any data passed through by the caller via the IUniswapV3PoolActions#swap call" + } + } + }, + "title": "A route processor for the Sushi Aggregator", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "algebraSwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IAlgebraPool#swap." + }, + "pancakeV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via PancakeV3Pool#swap." + }, + "processRoute(address,uint256,address,uint256,address,bytes)": { + "notice": "Processes the route generated off-chain. Has a lock" + }, + "processRouteWithTransferValueInput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value of input tokens to and then processes the route" + }, + "processRouteWithTransferValueOutput(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "processes the route and sends amount of output token to " + }, + "transferValueAndprocessRoute(address,uint256,address,uint256,address,uint256,address,bytes)": { + "notice": "Transfers some value to and then processes the route" + }, + "uniswapV3SwapCallback(int256,int256,bytes)": { + "notice": "Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 8573, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "priviledgedUsers", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 8575, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "lastCalledPool", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 8578, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "unlocked", + "offset": 20, + "slot": "2", + "type": "t_uint8" + }, + { + "astId": 8581, + "contract": "contracts/RouteProcessor5.sol:RouteProcessor5", + "label": "paused", + "offset": 21, + "slot": "2", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/protocols/route-processor/deployments/cronos/solcInputs/9252879aaeb02fabe759ce8768addec4.json b/protocols/route-processor/deployments/cronos/solcInputs/9252879aaeb02fabe759ce8768addec4.json new file mode 100644 index 0000000000..c6762a8dc1 --- /dev/null +++ b/protocols/route-processor/deployments/cronos/solcInputs/9252879aaeb02fabe759ce8768addec4.json @@ -0,0 +1,98 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\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 Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @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 `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, 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 `from` to `to` 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 from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.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 function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\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 * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 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 functionCallWithValue(target, data, 0, \"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 (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, 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 (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\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 /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\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" + }, + "contracts/Approve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\n\nlibrary Approve {\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "contracts/InputStream.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\n/** @notice Simple read stream */\nlibrary InputStream {\n\n /** @notice Creates stream from data\n * @param data data\n */\n function createStream(bytes memory data) internal pure returns (uint256 stream) {\n assembly {\n stream := mload(0x40)\n mstore(0x40, add(stream, 64))\n mstore(stream, data)\n let length := mload(data)\n mstore(add(stream, 32), add(data, length))\n }\n }\n\n /** @notice Checks if stream is not empty\n * @param stream stream\n */\n function isNotEmpty(uint256 stream) internal pure returns (bool) {\n uint256 pos;\n uint256 finish;\n assembly {\n pos := mload(stream)\n finish := mload(add(stream, 32))\n }\n return pos < finish;\n }\n\n /** @notice Reads uint8 from the stream\n * @param stream stream\n */\n function readUint8(uint256 stream) internal pure returns (uint8 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 1)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint16 from the stream\n * @param stream stream\n */\n function readUint16(uint256 stream) internal pure returns (uint16 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 2)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint24 from the stream\n * @param stream stream\n */\n function readUint24(uint256 stream) internal pure returns (uint24 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 3)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint32 from the stream\n * @param stream stream\n */\n function readUint32(uint256 stream) internal pure returns (uint32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 4)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads uint256 from the stream\n * @param stream stream\n */\n function readUint(uint256 stream) internal pure returns (uint256 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes32 from the stream\n * @param stream stream\n */\n function readBytes32(uint256 stream) internal pure returns (bytes32 res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 32)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads address from the stream\n * @param stream stream\n */\n function readAddress(uint256 stream) internal pure returns (address res) {\n assembly {\n let pos := mload(stream)\n pos := add(pos, 20)\n res := mload(pos)\n mstore(stream, pos)\n }\n }\n\n /** @notice Reads bytes from the stream\n * @param stream stream\n */\n function readBytes(uint256 stream) internal pure returns (bytes memory res) {\n assembly {\n let pos := mload(stream)\n res := add(pos, 32)\n let length := mload(res)\n mstore(stream, add(res, length))\n }\n }\n}\n" + }, + "contracts/RouteProcessor.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport './InputStream.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\naddress constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Okavango\ncontract RouteProcessor {\n using SafeERC20 for IERC20;\n using InputStream for uint256;\n\n IBentoBoxMinimal public immutable bentoBox;\n\n uint private unlocked = 1;\n modifier lock() {\n require(unlocked == 1, 'RouteProcessor is locked');\n unlocked = 2;\n _;\n unlocked = 1;\n }\n\n constructor(address _bentoBox) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n (bool success, bytes memory returnBytes) = transferValueTo.call{value: amountValueTransfer}('');\n require(success, string(abi.encodePacked(returnBytes)));\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 amountInAcc = 0;\n uint256 balanceInitial = tokenOut == NATIVE_ADDRESS ? \n address(to).balance : IERC20(tokenOut).balanceOf(to);\n\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode < 20) {\n if (commandCode == 10)\n swapUniswapPool(stream); // Sushi/Uniswap pool swap\n else if (commandCode == 4)\n distributeERC20Shares(stream); // distribute ERC20 tokens from this router to pools\n else if (commandCode == 3)\n amountInAcc += distributeERC20Amounts(stream, tokenIn); // initial distribution\n else if (commandCode == 5)\n amountInAcc += wrapAndDistributeERC20Amounts(stream); // wrap natives and initial distribution \n else if (commandCode == 6) \n unwrapNative(to, stream);\n else if (commandCode == 7)\n amountInAcc += distributeERC20AmountsFromRP(stream, tokenIn); // initial distribution\n else revert('Unknown command code');\n } else if (commandCode < 24) {\n if (commandCode == 20) bentoDepositAmountFromBento(stream, tokenIn);\n else if (commandCode == 21) swapTrident(stream);\n else if (commandCode == 23) bentoWithdrawShareFromRP(stream, tokenIn);\n else revert('Unknown command code');\n } else {\n if (commandCode == 24) amountInAcc += distributeBentoShares(stream, tokenIn);\n else if (commandCode == 25) distributeBentoPortions(stream);\n else if (commandCode == 26) bentoDepositAllFromBento(stream);\n else if (commandCode == 27) bentoWithdrawAllFromRP(stream);\n else revert('Unknown command code');\n }\n }\n\n require(amountInAcc == amountIn, 'Wrong amountIn value');\n uint256 balanceFinal = tokenOut == NATIVE_ADDRESS ? \n address(to).balance : IERC20(tokenOut).balanceOf(to);\n require(balanceFinal >= balanceInitial + amountOutMin, 'Minimal ouput balance violation');\n\n amountOut = balanceFinal - balanceInitial;\n }\n\n /// @notice Transfers input tokens sent to BentoBox to a pool\n /// @notice Expected to be called for initial liquidity transfer from user to BentoBox, so we know exact amounts\n /// @param stream [Pool, Amount]. Pool into which an amount of tokens will be transferred\n /// @param token Address of the token to transfer\n function bentoDepositAmountFromBento(uint256 stream, address token) private {\n address to = stream.readAddress();\n uint256 amount = stream.readUint();\n bentoBox.deposit(token, address(bentoBox), to, amount, 0);\n }\n\n /// @notice Transfers all available input tokens from BentoBox to a pool\n /// @param stream [Pool, Token]. Pool into which all tokens will be transferred \n function bentoDepositAllFromBento(uint256 stream) private {\n address to = stream.readAddress();\n address token = stream.readAddress();\n\n uint256 amount = IERC20(token).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(token).balance -\n bentoBox.totals(token).elastic;\n bentoBox.deposit(token, address(bentoBox), to, amount, 0);\n }\n\n /// @notice Withdraws BentoBox tokens from BentoBox to an address\n /// @param stream [To, Amount]. Destination where an amount of token will be transferred\n /// @param token Token to transfer\n function bentoWithdrawShareFromRP(uint256 stream, address token) private {\n address to = stream.readAddress();\n uint256 amount = stream.readUint();\n bentoBox.withdraw(token, address(this), to, amount, 0);\n }\n\n /// @notice Withdraws all available BentoBox tokens from BentoBox to an address\n /// @param stream [Token, To]. Token which will be transferred to a destination\n function bentoWithdrawAllFromRP(uint256 stream) private {\n address token = stream.readAddress();\n address to = stream.readAddress();\n uint256 amount = bentoBox.balanceOf(token, address(this));\n bentoBox.withdraw(token, address(this), to, 0, amount);\n }\n\n /// @notice Performs a Trident pool swap\n /// @param stream [Pool, SwapData]. Pool against a swap defined by SwapData will be executed\n function swapTrident(uint256 stream) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n IPool(pool).swap(swapData);\n }\n\n /// @notice Performs a Sushi/UniswapV2 pool swap\n /// @param stream [Pool, TokenIn, Direction, To]\n /// @return amountOut Amount of the output token\n function swapUniswapPool(uint256 stream) private returns (uint256 amountOut) {\n address pool = stream.readAddress();\n address tokenIn = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n\n uint256 amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn;\n uint256 amountInWithFee = amountIn * 997;\n amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Distributes input ERC20 tokens from msg.sender to addresses. Tokens should be approved\n /// @notice Expected to be called for initial liquidity transfer from the user to pools, so we know exact amounts\n /// @param stream [ArrayLength, ...[To, Amount][]]. An array of destinations and token amounts\n /// @param token Token to distribute\n /// @return amountTotal Total amount distributed\n function distributeERC20Amounts(uint256 stream, address token) private returns (uint256 amountTotal) {\n uint8 num = stream.readUint8();\n amountTotal = 0;\n for (uint256 i = 0; i < num; ++i) {\n address to = stream.readAddress();\n uint256 amount = stream.readUint();\n amountTotal += amount;\n IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n }\n\n /// @notice Distributes input ERC20 tokens from this contract to addresses. Tokens should be approved\n /// @notice Expected to be called for initial liquidity transfer from the user to pools, so we know exact amounts\n /// @param stream [ArrayLength, ...[To, Amount][]]. An array of destinations and token amounts\n /// @param token Token to distribute\n /// @return amountTotal Total amount distributed\n function distributeERC20AmountsFromRP(uint256 stream, address token) private returns (uint256 amountTotal) {\n uint8 num = stream.readUint8();\n amountTotal = 0;\n for (uint256 i = 0; i < num; ++i) {\n address to = stream.readAddress();\n uint256 amount = stream.readUint();\n amountTotal += amount;\n IERC20(token).safeTransfer(to, amount);\n }\n }\n\n /// @notice Wraps all native inputs and distributes wrapped ERC20 tokens from RouteProcessor to addresses\n /// @notice Expected to be called for initial liquidity transfer from the user to pools, so we know exact amounts\n /// @param stream [WrapToken, ArrayLength, ...[To, Amount][]]. An array of destinations and token amounts\n /// @return amountTotal Total amount distributed\n function wrapAndDistributeERC20Amounts(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n IWETH(token).deposit{value: address(this).balance}();\n uint8 num = stream.readUint8();\n amountTotal = 0;\n for (uint256 i = 0; i < num; ++i) {\n address to = stream.readAddress();\n uint256 amount = stream.readUint();\n amountTotal += amount;\n IERC20(token).safeTransfer(to, amount);\n }\n require(address(this).balance == 0, \"RouteProcessor: invalid input amount\");\n }\n\n /// @notice Distributes input BentoBox tokens from msg.sender to addresses. Tokens should be approved\n /// @notice Expected to be called for initial liquidity transfer from the user to pools, so we know exact amounts\n /// @param stream [ArrayLength, ...[To, ShareAmount][]]. An array of destinations and token share amounts\n /// @param token Token to distribute\n /// @return sharesTotal Total shares distributed\n function distributeBentoShares(uint256 stream, address token) private returns (uint256 sharesTotal) {\n uint8 num = stream.readUint8();\n sharesTotal = 0;\n for (uint256 i = 0; i < num; ++i) {\n address to = stream.readAddress();\n uint256 share = stream.readUint();\n sharesTotal += share;\n bentoBox.transfer(token, msg.sender, to, share);\n }\n }\n\n /// @notice Distributes ERC20 tokens from RouteProcessor to addresses\n /// @notice Quantity for sending is determined by share in 1/65535\n /// @notice During routing we can't predict in advance the actual value of internal swaps because of slippage,\n /// @notice so we have to work with shares - not fixed amounts\n /// @param stream [Token, ArrayLength, ...[To, ShareAmount][]]. Token to distribute. An array of destinations and token share amounts\n function distributeERC20Shares(uint256 stream) private {\n address token = stream.readAddress();\n uint8 num = stream.readUint8();\n uint256 amountTotal = IERC20(token).balanceOf(address(this))\n - 1; // slot undrain protection\n\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n address to = stream.readAddress();\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / 65535;\n amountTotal -= amount;\n IERC20(token).safeTransfer(to, amount);\n }\n }\n }\n\n /// @notice Distributes BentoBox tokens from RouteProcessor to addresses\n /// @notice Quantity for sending is determined by portions in 1/65535.\n /// @notice During routing we can't predict in advance the actual value of internal swaps because of slippage,\n /// @notice so we have to work with portions - not fixed amounts\n /// @param stream [Token, ArrayLength, ...[To, ShareAmount][]]. Token to distribute. An array of destinations and token share amounts\n function distributeBentoPortions(uint256 stream) private {\n address token = stream.readAddress();\n uint8 num = stream.readUint8();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this))\n - 1; // slot undrain protection\n\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n address to = stream.readAddress();\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / 65535;\n amountTotal -= amount;\n bentoBox.transfer(token, address(this), to, amount);\n }\n }\n }\n\n /// @notice Unwraps the Native Token\n /// @param receiver Destination of the unwrapped token\n /// @param stream [Token]. Token to unwrap native\n function unwrapNative(address receiver, uint256 stream) private {\n address token = stream.readAddress();\n IWETH(token).withdraw( IERC20(token).balanceOf(address(this))\n - 1); // slot undrain protection\n payable(receiver).transfer(address(this).balance);\n }\n}\n" + }, + "contracts/RouteProcessor3_1.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport './InputStream.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\n/// version 3.1\ncontract RouteProcessor3_1 is Ownable {\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint amountIn, \n uint amountOutMin,\n uint amountOut\n );\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = 1;\n uint8 private paused = 1;\n modifier lock() {\n require(unlocked == 1, 'RouteProcessor is locked');\n require(paused == 1, 'RouteProcessor is paused');\n unlocked = 2;\n _;\n unlocked = 1;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender] == true, \"RP: caller is not the owner or a priviledged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = 2;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = 1;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n (bool success, bytes memory returnBytes) = transferValueTo.call{value: amountValueTransfer}('');\n require(success, string(abi.encodePacked(returnBytes)));\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn == NATIVE_ADDRESS ? address(this).balance : IERC20(tokenIn).balanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut == NATIVE_ADDRESS ? address(to).balance : IERC20(tokenOut).balanceOf(to);\n\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) processMyERC20(stream);\n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) processNative(stream);\n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n }\n\n uint256 balanceInFinal = tokenIn == NATIVE_ADDRESS ? address(this).balance : IERC20(tokenIn).balanceOf(msg.sender);\n require(balanceInFinal + amountIn >= balanceInInitial, 'RouteProcessor: Minimal imput balance violation');\n\n uint256 balanceOutFinal = tokenOut == NATIVE_ADDRESS ? address(to).balance : IERC20(tokenOut).balanceOf(to);\n require(balanceOutFinal >= balanceOutInitial + amountOutMin, 'RouteProcessor: Minimal ouput balance violation');\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, amountIn, amountOutMin, amountOut);\n }\n\n function applyPermit(address tokenIn, uint256 stream) private {\n //address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s)\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed process program\n function processNative(uint256 stream) private {\n uint256 amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n function processMyERC20(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed process program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / 65535;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, address(this), token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint8 num = stream.readUint8();\n\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / 65535;\n amountTotal -= amount;\n swap(stream, address(this), token, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed process program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from != address(this)) IERC20(tokenIn).safeTransferFrom(from, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n payable(to).transfer(address(this).balance);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (amountIn != 0) {\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else IERC20(tokenIn).safeTransferFrom(from, address(bentoBox), amountIn);\n } else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (amountIn > 0) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n\n if (amountIn != 0) {\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else IERC20(tokenIn).safeTransferFrom(from, pool, amountIn);\n }\n // without 'else' in order to support tax tokens\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * 997;\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (amountIn != 0) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from != address(this)) {\n require(from == msg.sender, 'swapUniV3: unexpected from address');\n IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n }\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n\n // Normally, RouteProcessor shouldn't have any liquidity on board\n // If some liquidity exists, it is sweept by the next user that makes swap through these tokens\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n}\n" + }, + "contracts/RouteProcessor3_2.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport './InputStream.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\n/// version 3.2\ncontract RouteProcessor3_2 is Ownable {\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint amountIn, \n uint amountOutMin,\n uint amountOut\n );\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = 1;\n uint8 private paused = 1;\n modifier lock() {\n require(unlocked == 1, 'RouteProcessor is locked');\n require(paused == 1, 'RouteProcessor is paused');\n unlocked = 2;\n _;\n unlocked = 1;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender] == true, \"RP: caller is not the owner or a priviledged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = 2;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = 1;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n (bool success, bytes memory returnBytes) = transferValueTo.call{value: amountValueTransfer}('');\n require(success, string(abi.encodePacked(returnBytes)));\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn == NATIVE_ADDRESS ? address(this).balance : IERC20(tokenIn).balanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut == NATIVE_ADDRESS ? address(to).balance : IERC20(tokenOut).balanceOf(to);\n\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) processMyERC20(stream);\n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) processNative(stream);\n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n }\n\n uint256 balanceInFinal = tokenIn == NATIVE_ADDRESS ? address(this).balance : IERC20(tokenIn).balanceOf(msg.sender);\n require(balanceInFinal + amountIn >= balanceInInitial, 'RouteProcessor: Minimal imput balance violation');\n\n uint256 balanceOutFinal = tokenOut == NATIVE_ADDRESS ? address(to).balance : IERC20(tokenOut).balanceOf(to);\n require(balanceOutFinal >= balanceOutInitial + amountOutMin, 'RouteProcessor: Minimal ouput balance violation');\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, amountIn, amountOutMin, amountOut);\n }\n\n function applyPermit(address tokenIn, uint256 stream) private {\n //address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s)\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed process program\n function processNative(uint256 stream) private {\n uint256 amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n function processMyERC20(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed process program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / 65535;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, address(this), token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint8 num = stream.readUint8();\n\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / 65535;\n amountTotal -= amount;\n swap(stream, address(this), token, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed process program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from != address(this)) IERC20(tokenIn).safeTransferFrom(from, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n payable(to).transfer(address(this).balance);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (amountIn != 0) {\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else IERC20(tokenIn).safeTransferFrom(from, address(bentoBox), amountIn);\n } else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (amountIn > 0) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (amountIn != 0) {\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else IERC20(tokenIn).safeTransferFrom(from, pool, amountIn);\n }\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * 997;\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (amountIn != 0) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from != address(this)) {\n require(from == msg.sender, 'swapUniV3: unexpected from address');\n IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n }\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n\n // Normally, RouteProcessor shouldn't have any liquidity on board\n // If some liquidity exists, it is sweept by the next user that makes swap through these tokens\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n}\n" + }, + "contracts/RouteProcessor3.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport './InputStream.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\n/// version 2.1\ncontract RouteProcessor3 is Ownable {\n using SafeERC20 for IERC20;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint amountIn, \n uint amountOutMin,\n uint amountOut\n );\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = 1;\n uint8 private paused = 1;\n modifier lock() {\n require(unlocked == 1, 'RouteProcessor is locked');\n require(paused == 1, 'RouteProcessor is paused');\n unlocked = 2;\n _;\n unlocked = 1;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender] == true, \"RP: caller is not the owner or a priviledged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = 2;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = 1;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n (bool success, bytes memory returnBytes) = transferValueTo.call{value: amountValueTransfer}('');\n require(success, string(abi.encodePacked(returnBytes)));\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn == NATIVE_ADDRESS ? address(this).balance : IERC20(tokenIn).balanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut == NATIVE_ADDRESS ? address(to).balance : IERC20(tokenOut).balanceOf(to);\n\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) processMyERC20(stream);\n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) processNative(stream);\n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n }\n\n uint256 balanceInFinal = tokenIn == NATIVE_ADDRESS ? address(this).balance : IERC20(tokenIn).balanceOf(msg.sender);\n require(balanceInFinal + amountIn >= balanceInInitial, 'RouteProcessor: Minimal imput balance violation');\n\n uint256 balanceOutFinal = tokenOut == NATIVE_ADDRESS ? address(to).balance : IERC20(tokenOut).balanceOf(to);\n require(balanceOutFinal >= balanceOutInitial + amountOutMin, 'RouteProcessor: Minimal ouput balance violation');\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, amountIn, amountOutMin, amountOut);\n }\n\n function applyPermit(address tokenIn, uint256 stream) private {\n //address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s)\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed process program\n function processNative(uint256 stream) private {\n uint256 amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n function processMyERC20(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed process program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / 65535;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, address(this), token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed process program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint8 num = stream.readUint8();\n\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / 65535;\n amountTotal -= amount;\n swap(stream, address(this), token, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed process program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from != address(this)) IERC20(tokenIn).safeTransferFrom(from, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n payable(to).transfer(address(this).balance);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (amountIn != 0) {\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else IERC20(tokenIn).safeTransferFrom(from, address(bentoBox), amountIn);\n } else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (amountIn > 0) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n\n if (amountIn != 0) {\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else IERC20(tokenIn).safeTransferFrom(from, pool, amountIn);\n } else amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * 997;\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (amountIn != 0) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from != address(this)) {\n require(from == msg.sender, 'swapUniV3: unexpected from address');\n IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n }\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n\n // Normally, RouteProcessor shouldn't have any liquidity on board\n // If some liquidity exists, it is sweept by the next user that makes swap through these tokens\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n}\n" + }, + "contracts/RouteProcessor4.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Approve.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor4 is Ownable {\n using SafeERC20 for IERC20;\n using Approve for IERC20;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n (bool success, bytes memory returnBytes) = transferValueTo.call{value: amountValueTransfer}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn == NATIVE_ADDRESS ? 0 : IERC20(tokenIn).balanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut == NATIVE_ADDRESS ? address(to).balance : IERC20(tokenOut).balanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn == NATIVE_ADDRESS ? 0 : IERC20(tokenIn).balanceOf(msg.sender);\n require(balanceInFinal + amountIn >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut == NATIVE_ADDRESS ? address(to).balance : IERC20(tokenOut).balanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n (bool success,)= payable(to).call{value: amountIn}(\"\");\n require(success, \"RouteProcessor.wrapNative: Native token transfer failed\");\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = IERC20(tokenOut).balanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = IERC20(tokenOut).balanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) { \n if(tokenOut == NATIVE_ADDRESS) {\n (bool success,)= payable(to).call{value: amountOut}(\"\");\n require(success, \"RouteProcessor.swapCurve: Native token transfer failed\");\n } else {\n IERC20(tokenOut).safeTransfer(to, amountOut);\n }\n }\n }\n}\n" + }, + "contracts/RouteProcessor5.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '../interfaces/IUniswapV2Pair.sol';\nimport '../interfaces/IUniswapV3Pool.sol';\nimport '../interfaces/ITridentCLPool.sol';\nimport '../interfaces/IBentoBoxMinimal.sol';\nimport '../interfaces/IPool.sol';\nimport '../interfaces/IWETH.sol';\nimport '../interfaces/ICurve.sol';\nimport './InputStream.sol';\nimport './Utils.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\naddress constant IMPOSSIBLE_POOL_ADDRESS = 0x0000000000000000000000000000000000000001;\naddress constant INTERNAL_INPUT_SOURCE = 0x0000000000000000000000000000000000000000;\n\nuint8 constant LOCKED = 2;\nuint8 constant NOT_LOCKED = 1;\nuint8 constant PAUSED = 2;\nuint8 constant NOT_PAUSED = 1;\n\n/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)\nuint160 constant MIN_SQRT_RATIO = 4295128739;\n/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)\nuint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n/// @title A route processor for the Sushi Aggregator\n/// @author Ilya Lyalin\ncontract RouteProcessor5 is Ownable {\n using SafeERC20 for IERC20;\n using Utils for IERC20;\n using Utils for address;\n using SafeERC20 for IERC20Permit;\n using InputStream for uint256;\n\n event Route(\n address indexed from, \n address to, \n address indexed tokenIn, \n address indexed tokenOut, \n uint256 amountIn, \n uint256 amountOutMin,\n uint256 amountOut\n );\n\n error MinimalOutputBalanceViolation(uint256 amountOut);\n\n IBentoBoxMinimal public immutable bentoBox;\n mapping (address => bool) public priviledgedUsers;\n address private lastCalledPool;\n\n uint8 private unlocked = NOT_LOCKED;\n uint8 private paused = NOT_PAUSED;\n modifier lock() {\n require(unlocked == NOT_LOCKED, 'RouteProcessor is locked');\n require(paused == NOT_PAUSED, 'RouteProcessor is paused');\n unlocked = LOCKED;\n _;\n unlocked = NOT_LOCKED;\n }\n\n modifier onlyOwnerOrPriviledgedUser() {\n require(msg.sender == owner() || priviledgedUsers[msg.sender], \"RP: caller is not the owner or a privileged user\");\n _;\n }\n\n constructor(address _bentoBox, address[] memory priviledgedUserList) {\n bentoBox = IBentoBoxMinimal(_bentoBox);\n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n\n for (uint256 i = 0; i < priviledgedUserList.length; i++) {\n priviledgedUsers[priviledgedUserList[i]] = true;\n }\n }\n\n function setPriviledge(address user, bool priviledge) external onlyOwner {\n priviledgedUsers[user] = priviledge;\n }\n\n function pause() external onlyOwnerOrPriviledgedUser {\n paused = PAUSED;\n }\n\n function resume() external onlyOwnerOrPriviledgedUser {\n paused = NOT_PAUSED;\n }\n\n /// @notice For native unwrapping\n receive() external payable {}\n\n /// @notice Processes the route generated off-chain. Has a lock\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @param to Where to transfer output tokens\n /// @param route Route to process\n /// @return amountOut Actual amount of the output token\n function processRoute(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function transferValueAndprocessRoute(\n address transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n transferValueTo.transferNative(amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n\n /// @notice Transfers some value of input tokens to and then processes the route\n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueInput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n tokenIn.transferAnyFromSender(transferValueTo, amountValueTransfer);\n return processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, to, route);\n }\n \n /// @notice processes the route and sends amount of output token to \n /// @param transferValueTo Address where the value should be transferred\n /// @param amountValueTransfer How much value to transfer\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteWithTransferValueOutput(\n address payable transferValueTo,\n uint256 amountValueTransfer,\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) external payable lock returns (uint256 amountOut) {\n amountOut = processRouteInternal(tokenIn, amountIn, tokenOut, amountOutMin, address(this), route);\n tokenOut.transferAny(transferValueTo, amountValueTransfer);\n tokenOut.transferAny(to, amountOut - amountValueTransfer);\n }\n\n /// @notice Processes the route generated off-chain\n /// @param tokenIn Address of the input token\n /// @param amountIn Amount of the input token\n /// @param tokenOut Address of the output token\n /// @param amountOutMin Minimum amount of the output token\n /// @return amountOut Actual amount of the output token\n function processRouteInternal(\n address tokenIn,\n uint256 amountIn,\n address tokenOut,\n uint256 amountOutMin,\n address to,\n bytes memory route\n ) private returns (uint256 amountOut) {\n uint256 balanceInInitial = tokenIn.anyBalanceOf(msg.sender);\n uint256 balanceOutInitial = tokenOut.anyBalanceOf(to);\n\n uint256 realAmountIn = amountIn;\n {\n uint256 step = 0;\n uint256 stream = InputStream.createStream(route);\n while (stream.isNotEmpty()) {\n uint8 commandCode = stream.readUint8();\n if (commandCode == 1) {\n uint256 usedAmount = processMyERC20(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 2) processUserERC20(stream, amountIn);\n else if (commandCode == 3) {\n uint256 usedAmount = processNative(stream); \n if (step == 0) realAmountIn = usedAmount;\n } \n else if (commandCode == 4) processOnePool(stream);\n else if (commandCode == 5) processInsideBento(stream);\n else if (commandCode == 6) applyPermit(tokenIn, stream);\n else revert('RouteProcessor: Unknown command code');\n ++step;\n }\n }\n\n uint256 balanceInFinal = tokenIn.anyBalanceOf(msg.sender);\n if (tokenIn != Utils.NATIVE_ADDRESS)\n require(balanceInFinal + amountIn + 10 >= balanceInInitial, 'RouteProcessor: Minimal input balance violation');\n \n uint256 balanceOutFinal = tokenOut.anyBalanceOf(to);\n if (balanceOutFinal < balanceOutInitial + amountOutMin)\n revert MinimalOutputBalanceViolation(balanceOutFinal - balanceOutInitial);\n\n amountOut = balanceOutFinal - balanceOutInitial;\n\n emit Route(msg.sender, to, tokenIn, tokenOut, realAmountIn, amountOutMin, amountOut);\n }\n\n /// @notice Applies ERC-2612 permit\n /// @param tokenIn permitted token\n /// @param stream Streamed program\n function applyPermit(address tokenIn, uint256 stream) private {\n uint256 value = stream.readUint();\n uint256 deadline = stream.readUint();\n uint8 v = stream.readUint8();\n bytes32 r = stream.readBytes32();\n bytes32 s = stream.readBytes32();\n if (IERC20(tokenIn).allowance(msg.sender, address(this)) < value) {\n IERC20Permit(tokenIn).safePermit(msg.sender, address(this), value, deadline, v, r, s);\n }\n }\n\n /// @notice Processes native coin: call swap for all pools that swap from native coin\n /// @param stream Streamed program\n function processNative(uint256 stream) private returns (uint256 amountTotal) {\n amountTotal = address(this).balance;\n distributeAndSwap(stream, address(this), Utils.NATIVE_ADDRESS, amountTotal);\n }\n\n /// @notice Processes ERC20 token from this contract balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processMyERC20(uint256 stream) private returns (uint256 amountTotal) {\n address token = stream.readAddress();\n amountTotal = IERC20(token).balanceOf(address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n \n /// @notice Processes ERC20 token from msg.sender balance:\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n /// @param amountTotal Amount of tokens to take from msg.sender\n function processUserERC20(uint256 stream, uint256 amountTotal) private {\n address token = stream.readAddress();\n distributeAndSwap(stream, msg.sender, token, amountTotal);\n }\n\n /// @notice Processes ERC20 token for cases when the token has only one output pool\n /// @notice In this case liquidity is already at pool balance. This is an optimization\n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processOnePool(uint256 stream) private {\n address token = stream.readAddress();\n swap(stream, INTERNAL_INPUT_SOURCE, token, 0);\n }\n\n /// @notice Processes Bento tokens \n /// @notice Call swap for all pools that swap from this token\n /// @param stream Streamed program\n function processInsideBento(uint256 stream) private {\n address token = stream.readAddress();\n uint256 amountTotal = bentoBox.balanceOf(token, address(this));\n unchecked {\n if (amountTotal > 0) amountTotal -= 1; // slot undrain protection\n }\n distributeAndSwap(stream, address(this), token, amountTotal);\n }\n\n /// @notice Distributes amountTotal to several pools according to their shares and calls swap for each pool\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountTotal Total amount of tokenIn for swaps \n function distributeAndSwap(uint256 stream, address from, address tokenIn, uint256 amountTotal) private {\n uint8 num = stream.readUint8();\n unchecked {\n for (uint256 i = 0; i < num; ++i) {\n uint16 share = stream.readUint16();\n uint256 amount = (amountTotal * share) / type(uint16).max /*65535*/;\n amountTotal -= amount;\n swap(stream, from, tokenIn, amount);\n }\n }\n }\n\n /// @notice Makes swap\n /// @param stream Streamed program\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swap(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 poolType = stream.readUint8();\n if (poolType == 0) swapUniV2(stream, from, tokenIn, amountIn);\n else if (poolType == 1) swapUniV3(stream, from, tokenIn, amountIn);\n else if (poolType == 2) wrapNative(stream, from, tokenIn, amountIn);\n else if (poolType == 3) bentoBridge(stream, from, tokenIn, amountIn);\n else if (poolType == 4) swapTrident(stream, from, tokenIn, amountIn);\n else if (poolType == 5) swapCurve(stream, from, tokenIn, amountIn);\n else revert('RouteProcessor: Unknown pool type');\n }\n\n /// @notice Wraps/unwraps native token\n /// @param stream [direction & fake, recipient, wrapToken?]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function wrapNative(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 directionAndFake = stream.readUint8();\n address to = stream.readAddress();\n\n if (directionAndFake & 1 == 1) { // wrap native\n address wrapToken = stream.readAddress();\n if (directionAndFake & 2 == 0) IWETH(wrapToken).deposit{value: amountIn}();\n if (to != address(this)) IERC20(wrapToken).safeTransfer(to, amountIn);\n } else { // unwrap native\n if (directionAndFake & 2 == 0) {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IWETH(tokenIn).withdraw(amountIn);\n }\n to.transferNative(amountIn);\n }\n }\n\n /// @notice Bridge/unbridge tokens to/from Bento\n /// @param stream [direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function bentoBridge(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n\n if (direction > 0) { // outside to Bento\n // deposit to arbitrary recipient is possible only from address(bentoBox)\n if (from == address(this)) IERC20(tokenIn).safeTransfer(address(bentoBox), amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(bentoBox), amountIn);\n else {\n // tokens already are at address(bentoBox)\n amountIn = IERC20(tokenIn).balanceOf(address(bentoBox)) +\n bentoBox.strategyData(tokenIn).balance -\n bentoBox.totals(tokenIn).elastic;\n }\n bentoBox.deposit(tokenIn, address(bentoBox), to, amountIn, 0);\n } else { // Bento to outside\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, address(this), amountIn);\n } else amountIn = bentoBox.balanceOf(tokenIn, address(this));\n bentoBox.withdraw(tokenIn, address(this), to, 0, amountIn);\n }\n }\n\n /// @notice UniswapV2 pool swap\n /// @param stream [pool, direction, recipient, fee]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV2(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 direction = stream.readUint8();\n address to = stream.readAddress();\n uint24 fee = stream.readUint24(); // pool fee in 1/1_000_000\n\n if (from == address(this)) IERC20(tokenIn).safeTransfer(pool, amountIn);\n else if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, pool, amountIn);\n\n (uint256 r0, uint256 r1, ) = IUniswapV2Pair(pool).getReserves();\n require(r0 > 0 && r1 > 0, 'Wrong pool reserves');\n (uint256 reserveIn, uint256 reserveOut) = direction == 1 ? (r0, r1) : (r1, r0);\n amountIn = IERC20(tokenIn).balanceOf(pool) - reserveIn; // tokens already were transferred\n\n uint256 amountInWithFee = amountIn * (1_000_000 - fee);\n uint256 amountOut = (amountInWithFee * reserveOut) / (reserveIn * 1_000_000 + amountInWithFee);\n (uint256 amount0Out, uint256 amount1Out) = direction == 1 ? (uint256(0), amountOut) : (amountOut, uint256(0));\n IUniswapV2Pair(pool).swap(amount0Out, amount1Out, to, new bytes(0));\n }\n\n /// @notice Trident pool swap\n /// @param stream [pool, swapData]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapTrident(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bytes memory swapData = stream.readBytes();\n\n if (from != INTERNAL_INPUT_SOURCE) {\n bentoBox.transfer(tokenIn, from, pool, amountIn);\n }\n \n IPool(pool).swap(swapData);\n }\n\n /// @notice UniswapV3 pool swap\n /// @param stream [pool, direction, recipient]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapUniV3(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n bool zeroForOne = stream.readUint8() > 0;\n address recipient = stream.readAddress();\n\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), uint256(amountIn));\n\n lastCalledPool = pool;\n IUniswapV3Pool(pool).swap(\n recipient,\n zeroForOne,\n int256(amountIn),\n zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1,\n abi.encode(tokenIn)\n );\n require(lastCalledPool == IMPOSSIBLE_POOL_ADDRESS, 'RouteProcessor.swapUniV3: unexpected'); // Just to be sure\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call\n function uniswapV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) public {\n require(msg.sender == lastCalledPool, 'RouteProcessor.uniswapV3SwapCallback: call from unknown source');\n int256 amount = amount0Delta > 0 ? amount0Delta : amount1Delta;\n require(amount > 0, 'RouteProcessor.uniswapV3SwapCallback: not positive amount');\n \n lastCalledPool = IMPOSSIBLE_POOL_ADDRESS;\n (address tokenIn) = abi.decode(data, (address));\n IERC20(tokenIn).safeTransfer(msg.sender, uint256(amount));\n }\n\n /// @notice Called to `msg.sender` after executing a swap via IAlgebraPool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// The caller of this method _must_ be checked to be a AlgebraPool deployed by the canonical AlgebraFactory.\n /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the IAlgebraPoolActions#swap call\n function algebraSwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Called to `msg.sender` after executing a swap via PancakeV3Pool#swap.\n /// @dev In the implementation you must pay the pool tokens owed for the swap.\n /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token0 to the pool.\n /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by\n /// the end of the swap. If positive, the callback must send that amount of token1 to the pool.\n /// @param data Any data passed through by the caller via the PancakeV3Pool#swap call\n function pancakeV3SwapCallback(\n int256 amount0Delta,\n int256 amount1Delta,\n bytes calldata data\n ) external {\n uniswapV3SwapCallback(amount0Delta, amount1Delta, data);\n }\n\n /// @notice Curve pool swap. Legacy pools that don't return amountOut and have native coins are not supported\n /// @param stream [pool, poolType, fromIndex, toIndex, recipient, output token]\n /// @param from Where to take liquidity for swap\n /// @param tokenIn Input token\n /// @param amountIn Amount of tokenIn to take for swap\n function swapCurve(uint256 stream, address from, address tokenIn, uint256 amountIn) private {\n address pool = stream.readAddress();\n uint8 poolType = stream.readUint8();\n int128 fromIndex = int8(stream.readUint8());\n int128 toIndex = int8(stream.readUint8());\n address to = stream.readAddress();\n address tokenOut = stream.readAddress();\n\n uint256 amountOut;\n if (tokenIn == Utils.NATIVE_ADDRESS) {\n amountOut = ICurve(pool).exchange{value: amountIn}(fromIndex, toIndex, amountIn, 0);\n } else {\n if (from == msg.sender) IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);\n IERC20(tokenIn).approveSafe(pool, amountIn);\n if (poolType == 0) amountOut = ICurve(pool).exchange(fromIndex, toIndex, amountIn, 0);\n else {\n uint256 balanceBefore = tokenOut.anyBalanceOf(address(this));\n ICurveLegacy(pool).exchange(fromIndex, toIndex, amountIn, 0);\n uint256 balanceAfter = tokenOut.anyBalanceOf(address(this));\n amountOut = balanceAfter - balanceBefore;\n }\n }\n\n if (to != address(this)) tokenOut.transferAny(to, amountOut);\n }\n}\n" + }, + "contracts/Utils.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity 0.8.10;\n\nimport '@openzeppelin/contracts/token/ERC20/IERC20.sol';\nimport '@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol';\n\nlibrary Utils {\n using SafeERC20 for IERC20;\n\n address constant NATIVE_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n /**\n * @dev returns user's balance of token (or native)\n */\n function anyBalanceOf(address token, address user) internal view returns (uint256) {\n if (token == NATIVE_ADDRESS) return address(user).balance;\n else return IERC20(token).balanceOf(user);\n }\n\n /**\n * @dev transfers native with correct revert bubble up\n */\n function transferNative(address to, uint256 amount) internal {\n (bool success, bytes memory returnBytes) = to.call{value: amount}('');\n if (!success) {\n assembly {\n revert(add(32, returnBytes), mload(returnBytes))\n }\n }\n }\n\n /**\n * @dev transfers ERC20 or native\n */\n function transferAny(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount);\n else IERC20(token).safeTransfer(to, amount);\n }\n\n /**\n * @dev transfers from ERC20 or transfers native\n */\n function transferAnyFromSender(address token, address to, uint256 amount) internal {\n if (token == NATIVE_ADDRESS) transferNative(to, amount); // native liquidity is already on this contract\n else IERC20(token).safeTransferFrom(msg.sender, to, amount);\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which returns bool or nothing (USDT for example)\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveStable(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n (bool success, bytes memory data) = address(token).call(\n abi.encodeWithSelector(token.approve.selector, spender, amount)\n );\n return success && (data.length == 0 || abi.decode(data, (bool)));\n }\n\n /**\n * @dev ERC20 approve that correct works with token.approve which reverts if amount and \n * current allowance are not zero simultaniously (USDT for example). \n * In second case it tries to set allowance to 0, and then back to amount.\n * @param token The token targeted by the call.\n * @param spender token spender\n * @param amount token amount\n */\n function approveSafe(IERC20 token, address spender, uint256 amount) internal returns (bool) {\n return approveStable(token, spender, amount) \n || (approveStable(token, spender, 0) && approveStable(token, spender, amount));\n }\n}\n" + }, + "interfaces/IBentoBoxMinimal.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\nstruct Rebase {\n uint128 elastic;\n uint128 base;\n}\n\nstruct StrategyData {\n uint64 strategyStartDate;\n uint64 targetPercentage;\n uint128 balance; // the balance of the strategy that BentoBox thinks is in there\n}\n\n/// @notice A rebasing library\nlibrary RebaseLibrary {\n /// @notice Calculates the base value in relationship to `elastic` and `total`.\n function toBase(Rebase memory total, uint256 elastic) internal pure returns (uint256 base) {\n if (total.elastic == 0) {\n base = elastic;\n } else {\n base = (elastic * total.base) / total.elastic;\n }\n }\n\n /// @notice Calculates the elastic value in relationship to `base` and `total`.\n function toElastic(Rebase memory total, uint256 base) internal pure returns (uint256 elastic) {\n if (total.base == 0) {\n elastic = base;\n } else {\n elastic = (base * total.elastic) / total.base;\n }\n }\n}\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n function strategyData(address token) external view returns (StrategyData memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n" + }, + "interfaces/ICurve.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\n\npragma solidity >=0.8.0;\n\ninterface ICurve {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external returns (uint256);\n}\n\ninterface ICurveLegacy {\n function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) payable external;\n}\n\n" + }, + "interfaces/IPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.5.0;\npragma experimental ABIEncoderV2;\n\n/// @notice Trident pool interface.\ninterface IPool {\n /// @notice Executes a swap from one token to another.\n /// @dev The input tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function swap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Executes a swap from one token to another with a callback.\n /// @dev This function allows borrowing the output tokens and sending the input tokens in the callback.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that were sent to the user.\n function flashSwap(bytes calldata data) external returns (uint256 finalAmountOut);\n\n /// @notice Mints liquidity tokens.\n /// @param data ABI-encoded params that the pool requires.\n /// @return liquidity The amount of liquidity tokens that were minted for the user.\n function mint(bytes calldata data) external returns (uint256 liquidity);\n\n /// @notice Burns liquidity tokens.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return withdrawnAmounts The amount of various output tokens that were sent to the user.\n function burn(bytes calldata data) external returns (TokenAmount[] memory withdrawnAmounts);\n\n /// @notice Burns liquidity tokens for a single output token.\n /// @dev The input LP tokens must've already been sent to the pool.\n /// @param data ABI-encoded params that the pool requires.\n /// @return amountOut The amount of output tokens that were sent to the user.\n function burnSingle(bytes calldata data) external returns (uint256 amountOut);\n\n /// @return A unique identifier for the pool type.\n function poolIdentifier() external pure returns (bytes32);\n\n /// @return An array of tokens supported by the pool.\n function getAssets() external view returns (address[] memory);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountOut The amount of output tokens that will be sent to the user if the trade is executed.\n function getAmountOut(bytes calldata data) external view returns (uint256 finalAmountOut);\n\n /// @notice Simulates a trade and returns the expected output.\n /// @dev The pool does not need to include a trade simulator directly in itself - it can use a library.\n /// @param data ABI-encoded params that the pool requires.\n /// @return finalAmountIn The amount of input tokens that are required from the user if the trade is executed.\n function getAmountIn(bytes calldata data) external view returns (uint256 finalAmountIn);\n\n /// @dev This event must be emitted on all swaps.\n event Swap(address indexed recipient, address indexed tokenIn, address indexed tokenOut, uint256 amountIn, uint256 amountOut);\n\n /// @dev This struct frames output tokens for burns.\n struct TokenAmount {\n address token;\n uint256 amount;\n }\n}\n" + }, + "interfaces/ITridentCLPool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface ITridentCLPool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bool unwrapBento,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IUniswapV2Pair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}" + }, + "interfaces/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IUniswapV3Pool {\n function token0() external returns (address);\n function token1() external returns (address);\n\n function swap(\n address recipient,\n bool zeroForOne,\n int256 amountSpecified,\n uint160 sqrtPriceLimitX96,\n bytes calldata data\n ) external returns (int256 amount0, int256 amount1);\n}\n" + }, + "interfaces/IWETH.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity 0.8.10;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 10000000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file From af8760083d5598cabcbb22b36cad7bb41424a517 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Thu, 8 Aug 2024 09:34:48 +0100 Subject: [PATCH 099/125] fix: include route; --- apis/router/src/handlers/swap/index.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apis/router/src/handlers/swap/index.ts b/apis/router/src/handlers/swap/index.ts index 37713b2e35..e5f8e1b5b9 100644 --- a/apis/router/src/handlers/swap/index.ts +++ b/apis/router/src/handlers/swap/index.ts @@ -166,6 +166,8 @@ function handler( : undefined, routeProcessorAddress, true, + false, + true ) // we want to return { route, tx: { from, to, gas, gasPrice, value, input } } From ab87663c4d9694e2efb4d03c18602666348bb399 Mon Sep 17 00:00:00 2001 From: matthewlilley Date: Thu, 8 Aug 2024 08:36:11 +0000 Subject: [PATCH 100/125] chore: lint --- apis/router/src/handlers/swap/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apis/router/src/handlers/swap/index.ts b/apis/router/src/handlers/swap/index.ts index e5f8e1b5b9..5c19503b00 100644 --- a/apis/router/src/handlers/swap/index.ts +++ b/apis/router/src/handlers/swap/index.ts @@ -167,7 +167,7 @@ function handler( routeProcessorAddress, true, false, - true + true, ) // we want to return { route, tx: { from, to, gas, gasPrice, value, input } } From 98f05b9f2ff3103d1556c60ed0da50be499d4324 Mon Sep 17 00:00:00 2001 From: 0xMasayoshi <0xMasayoshi@protonmail.com> Date: Thu, 8 Aug 2024 17:16:03 +0700 Subject: [PATCH 101/125] chore: replace useCall with useEstimateGas --- apps/web/src/lib/hooks/useSimulateTrade.ts | 32 ++++++++++--------- .../simple-swap-trade-review-dialog.tsx | 2 +- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/apps/web/src/lib/hooks/useSimulateTrade.ts b/apps/web/src/lib/hooks/useSimulateTrade.ts index 324cd81e87..9212ccad22 100644 --- a/apps/web/src/lib/hooks/useSimulateTrade.ts +++ b/apps/web/src/lib/hooks/useSimulateTrade.ts @@ -1,14 +1,18 @@ import { UseTradeReturn } from '@sushiswap/react-query' +import { EstimateGasErrorType, EstimateGasReturnType } from '@wagmi/core' import { useEffect, useMemo, useRef } from 'react' import { useDerivedStateSimpleSwap } from 'src/ui/swap/simple/derivedstate-simple-swap-provider' import { isRouteProcessor5ChainId } from 'sushi/config' -import { CallErrorType, CallReturnType, Hex, RawContractError } from 'viem' -import { useAccount, useCall } from 'wagmi' +import { Hex, RawContractError } from 'viem' +import { useAccount, useEstimateGas } from 'wagmi' import { getTokenTax } from '../swap/getTokenTax' -const isMinOutError = (_error: CallErrorType): Hex | false => { - const error = _error.walk() as RawContractError - const data = typeof error?.data === 'object' ? error.data?.data : error.data +const isMinOutError = (_error: EstimateGasErrorType): Hex | false => { + const error = + _error.name === 'EstimateGasExecutionError' + ? (_error.walk() as RawContractError) + : undefined + const data = typeof error?.data === 'object' ? error.data?.data : error?.data return data?.includes('0x963b34a5') ? data : false } @@ -26,7 +30,7 @@ export function useSimulateTrade({ const { address } = useAccount() - const simulateTrade = useCall({ + const simulateTrade = useEstimateGas({ chainId: chainId, to: trade?.tx?.to, data: trade?.tx?.data as Hex | undefined, @@ -53,8 +57,8 @@ export function useSimulateTrade({ }, }) - const prevErrorRef = useRef() - const prevDataRef = useRef() + const prevErrorRef = useRef() + const prevDataRef = useRef() // onSuccess useEffect(() => { @@ -92,13 +96,11 @@ export function useSimulateTrade({ ...simulateTrade, data: simulateTrade.data ? { - ...simulateTrade.data, - request: { - to: trade?.tx?.to, - data: trade?.tx?.data as Hex | undefined, - value: trade?.tx?.value || 0n, - account: address, - }, + gas: (simulateTrade.data * 120n) / 100n, + to: trade?.tx?.to, + data: trade?.tx?.data as Hex | undefined, + value: trade?.tx?.value || 0n, + account: address, } : undefined, isError: diff --git a/apps/web/src/ui/swap/simple/simple-swap-trade-review-dialog.tsx b/apps/web/src/ui/swap/simple/simple-swap-trade-review-dialog.tsx index 3c670cd574..25fc005281 100644 --- a/apps/web/src/ui/swap/simple/simple-swap-trade-review-dialog.tsx +++ b/apps/web/src/ui/swap/simple/simple-swap-trade-review-dialog.tsx @@ -383,7 +383,7 @@ export const SimpleSwapTradeReviewDialog: FC<{ return async (confirm: () => void) => { try { - await sendTransactionAsync(simulation.request) + await sendTransactionAsync(simulation) confirm() } catch {} } From 346f41625a7e476e61f4a9b349ea554261ac4d97 Mon Sep 17 00:00:00 2001 From: 0xMasayoshi <0xMasayoshi@protonmail.com> Date: Thu, 8 Aug 2024 20:03:26 +0700 Subject: [PATCH 102/125] fix: navbar chain & account flicker on mount --- .../lib/wagmi/components/header-network-selector.tsx | 12 +++--------- .../src/lib/wagmi/components/user-profile/index.tsx | 4 +--- .../lib/wagmi/components/wagmi-header-components.tsx | 9 ++------- 3 files changed, 6 insertions(+), 19 deletions(-) diff --git a/apps/web/src/lib/wagmi/components/header-network-selector.tsx b/apps/web/src/lib/wagmi/components/header-network-selector.tsx index a1dc4ad0a3..8161df5473 100644 --- a/apps/web/src/lib/wagmi/components/header-network-selector.tsx +++ b/apps/web/src/lib/wagmi/components/header-network-selector.tsx @@ -1,4 +1,3 @@ -import { useIsMounted } from '@sushiswap/hooks' import { createErrorToast } from '@sushiswap/notifications' import { Button } from '@sushiswap/ui' import { NetworkSelector, NetworkSelectorOnSelectCallback } from '@sushiswap/ui' @@ -13,7 +12,6 @@ export const HeaderNetworkSelector: FC<{ selectedNetwork?: ChainId onChange?(chainId: ChainId): void }> = ({ networks, selectedNetwork, onChange }) => { - const isMounted = useIsMounted() const { switchChainAsync } = useSwitchChain() const chainId = useChainId() @@ -41,21 +39,17 @@ export const HeaderNetworkSelector: FC<{ [chainId, onChange, selectedNetwork, switchChainAsync], ) - const selected = isMounted - ? selectedNetwork || chainId || ChainId.ETHEREUM - : ChainId.ETHEREUM - return ( diff --git a/apps/web/src/lib/wagmi/components/user-profile/index.tsx b/apps/web/src/lib/wagmi/components/user-profile/index.tsx index 1ca7071232..a2665569f3 100644 --- a/apps/web/src/lib/wagmi/components/user-profile/index.tsx +++ b/apps/web/src/lib/wagmi/components/user-profile/index.tsx @@ -1,6 +1,5 @@ 'use client' -import { useIsMounted } from '@sushiswap/hooks' import { InterfaceEventName, sendAnalyticsEvent } from '@sushiswap/telemetry' import { cloudinaryFetchLoader } from '@sushiswap/ui' import { Button } from '@sushiswap/ui' @@ -23,7 +22,6 @@ interface ProfileProps { } export const UserProfile: FC = () => { - const isMounted = useIsMounted() const [view, setView] = useState(ProfileView.Default) const chainId = useChainId() const { address, isConnected } = useAccount() @@ -38,7 +36,7 @@ export const UserProfile: FC = () => { chainId: ChainId.ETHEREUM, }) - if (!address || !isMounted) return + if (!address) return return ( diff --git a/apps/web/src/lib/wagmi/components/wagmi-header-components.tsx b/apps/web/src/lib/wagmi/components/wagmi-header-components.tsx index af09219e6f..7bc559a161 100644 --- a/apps/web/src/lib/wagmi/components/wagmi-header-components.tsx +++ b/apps/web/src/lib/wagmi/components/wagmi-header-components.tsx @@ -15,13 +15,11 @@ import { UserProfile } from './user-profile' interface WagmiHeaderComponentsProps { chainIds: ChainId[] - selectedNetwork?: ChainId onChange?(chainId: ChainId): void } export const WagmiHeaderComponents: React.FC = ({ chainIds, - selectedNetwork, onChange, }) => { const { chainId, address, connector } = useAccount() @@ -40,13 +38,10 @@ export const WagmiHeaderComponents: React.FC = ({ }) } }, [address, chainId, connector, previousConnectedChainId]) + return ( <> - + ) From 6f9928743f0faa4ce38a191e52151cc131733d0d Mon Sep 17 00:00:00 2001 From: LufyCZ Date: Thu, 8 Aug 2024 22:15:49 +0000 Subject: [PATCH 103/125] feat: move DEFAULT_BASES to the sushi package --- .../token-selector/TokenSelector.tsx | 8 +- packages/hooks/src/usePinnedTokens.ts | 380 +---------------- packages/sushi/src/config/default-bases.ts | 381 ++++++++++++++++++ packages/sushi/src/config/index.ts | 1 + 4 files changed, 385 insertions(+), 385 deletions(-) create mode 100644 packages/sushi/src/config/default-bases.ts diff --git a/apps/web/src/lib/wagmi/components/token-selector/TokenSelector.tsx b/apps/web/src/lib/wagmi/components/token-selector/TokenSelector.tsx index 91c1fed65c..8e9a6e4bb4 100644 --- a/apps/web/src/lib/wagmi/components/token-selector/TokenSelector.tsx +++ b/apps/web/src/lib/wagmi/components/token-selector/TokenSelector.tsx @@ -2,12 +2,7 @@ import { XMarkIcon } from '@heroicons/react/20/solid' import { MagnifyingGlassIcon } from '@heroicons/react/24/solid' -import { - DEFAULT_BASES, - useCustomTokens, - useDebounce, - usePinnedTokens, -} from '@sushiswap/hooks' +import { useCustomTokens, useDebounce, usePinnedTokens } from '@sushiswap/hooks' import { NativeAddress, useBalances, @@ -48,6 +43,7 @@ import React, { useState, } from 'react' import { ChainId } from 'sushi/chain' +import { DEFAULT_BASES } from 'sushi/config' import { Native, Token, Type } from 'sushi/currency' import { isAddress } from 'viem' import { useAccount } from 'wagmi' diff --git a/packages/hooks/src/usePinnedTokens.ts b/packages/hooks/src/usePinnedTokens.ts index 64e41b96fe..9332ad0e50 100644 --- a/packages/hooks/src/usePinnedTokens.ts +++ b/packages/hooks/src/usePinnedTokens.ts @@ -1,388 +1,10 @@ 'use client' import { useCallback, useMemo } from 'react' -import { ChainId } from 'sushi/chain' -import { - STARGATE_USDC, - STARGATE_USDT, - STARGATE_WBTC, - STARGATE_WETH, -} from 'sushi/config' -import { - ARB, - DAI, - FRAX, - GNO, - MATIC, - MIM, - SKL, - SUSHI, - USDB, - USDC, - USDT, - WBTC, - WETH9, - WNATIVE, - WORMHOLE_USDC, - WORMHOLE_WBTC, - WORMHOLE_WETH, - ZETA_ETH_BRIDGE_USDC, - ZETA_ETH_BRIDGE_USDT, - axlDAI, - axlETH, - axlUSDC, - axlUSDT, - axlWBTC, -} from 'sushi/currency' -import { type Currency, Native, Token } from 'sushi/currency' +import { type Currency } from 'sushi/currency' import { getAddress as _getAddress, isAddress } from 'viem/utils' import { useLocalStorage } from './useLocalStorage' -export const DEFAULT_BASES = { - [ChainId.ETHEREUM]: [ - Native.onChain(ChainId.ETHEREUM), - WNATIVE[ChainId.ETHEREUM], - SUSHI[ChainId.ETHEREUM], - WBTC[ChainId.ETHEREUM], - USDC[ChainId.ETHEREUM], - USDT[ChainId.ETHEREUM], - DAI[ChainId.ETHEREUM], - ], - [ChainId.SEPOLIA]: [ - Native.onChain(ChainId.SEPOLIA), - WNATIVE[ChainId.SEPOLIA], - USDC[ChainId.SEPOLIA], - ], - // [ChainId.ROPSTEN]: [], - // [ChainId.RINKEBY]: [], - // [ChainId.GÖRLI]: [], - // [ChainId.KOVAN]: [], - [ChainId.GNOSIS]: [ - Native.onChain(ChainId.GNOSIS), - WNATIVE[ChainId.GNOSIS], - GNO[ChainId.GNOSIS], - WETH9[ChainId.GNOSIS], - USDC[ChainId.GNOSIS], - USDT[ChainId.GNOSIS], - DAI[ChainId.GNOSIS], - ], - [ChainId.BSC]: [ - Native.onChain(ChainId.BSC), - WNATIVE[ChainId.BSC], - WETH9[ChainId.BSC], - USDC[ChainId.BSC], - USDT[ChainId.BSC], - DAI[ChainId.BSC], - ], - [ChainId.BSC_TESTNET]: [], - [ChainId.POLYGON]: [ - Native.onChain(ChainId.POLYGON), - WNATIVE[ChainId.POLYGON], - WBTC[ChainId.POLYGON], - WETH9[ChainId.POLYGON], - USDC[ChainId.POLYGON], - USDT[ChainId.POLYGON], - DAI[ChainId.POLYGON], - ], - [ChainId.POLYGON_TESTNET]: [], - [ChainId.AVALANCHE]: [ - Native.onChain(ChainId.AVALANCHE), - WNATIVE[ChainId.AVALANCHE], - WETH9[ChainId.AVALANCHE], - WBTC[ChainId.AVALANCHE], - USDC[ChainId.AVALANCHE], - USDT[ChainId.AVALANCHE], - DAI[ChainId.AVALANCHE], - MIM[ChainId.AVALANCHE], - FRAX[ChainId.AVALANCHE], - ], - [ChainId.AVALANCHE_TESTNET]: [], - [ChainId.ARBITRUM_NOVA]: [ - Native.onChain(ChainId.ARBITRUM_NOVA), - WNATIVE[ChainId.ARBITRUM_NOVA], - ARB[ChainId.ARBITRUM_NOVA], - WBTC[ChainId.ARBITRUM_NOVA], - USDC[ChainId.ARBITRUM_NOVA], - USDT[ChainId.ARBITRUM_NOVA], - DAI[ChainId.ARBITRUM_NOVA], - ], - [ChainId.BOBA]: [ - Native.onChain(ChainId.BOBA), - WNATIVE[ChainId.BOBA], - USDC[ChainId.BOBA], - USDT[ChainId.BOBA], - DAI[ChainId.BOBA], - FRAX[ChainId.BOBA], - WBTC[ChainId.BOBA], - ], - [ChainId.FANTOM]: [ - Native.onChain(ChainId.FANTOM), - WNATIVE[ChainId.FANTOM], - axlUSDC[ChainId.FANTOM], - STARGATE_USDC[ChainId.FANTOM], - STARGATE_USDT[ChainId.FANTOM], - STARGATE_WETH[ChainId.FANTOM], - STARGATE_WBTC[ChainId.FANTOM], - axlUSDC[ChainId.FANTOM], - MIM[ChainId.FANTOM], - ], - [ChainId.FANTOM_TESTNET]: [], - [ChainId.ARBITRUM]: [ - Native.onChain(ChainId.ARBITRUM), - WNATIVE[ChainId.ARBITRUM], - ARB[ChainId.ARBITRUM], - WBTC[ChainId.ARBITRUM], - USDC[ChainId.ARBITRUM], - USDT[ChainId.ARBITRUM], - DAI[ChainId.ARBITRUM], - MIM[ChainId.ARBITRUM], - ], - [ChainId.ARBITRUM_TESTNET]: [], - [ChainId.HARMONY]: [ - Native.onChain(ChainId.HARMONY), - WNATIVE[ChainId.HARMONY], - WETH9[ChainId.HARMONY], - USDC[ChainId.HARMONY], - USDT[ChainId.HARMONY], - DAI[ChainId.HARMONY], - ], - // [ChainId.HARMONY_TESTNET]: [], - [ChainId.HECO]: [ - Native.onChain(ChainId.HECO), - WNATIVE[ChainId.HECO], - WETH9[ChainId.HECO], - USDC[ChainId.HECO], - USDT[ChainId.HECO], - DAI[ChainId.HECO], - ], - // [ChainId.HECO_TESTNET]: [], - [ChainId.OKEX]: [ - Native.onChain(ChainId.OKEX), - WNATIVE[ChainId.OKEX], - WETH9[ChainId.OKEX], - USDC[ChainId.OKEX], - USDT[ChainId.OKEX], - DAI[ChainId.OKEX], - ], - // [ChainId.OKEX_TESTNET]: [], - [ChainId.CELO]: [ - Native.onChain(ChainId.CELO), - // WNATIVE[ChainId.CELO], - WETH9[ChainId.CELO], - USDC[ChainId.CELO], - USDT[ChainId.CELO], - DAI[ChainId.CELO], - ], - [ChainId.PALM]: [ - Native.onChain(ChainId.PALM), - WNATIVE[ChainId.PALM], - WETH9[ChainId.PALM], - ], - [ChainId.MOONRIVER]: [ - Native.onChain(ChainId.MOONRIVER), - WNATIVE[ChainId.MOONRIVER], - WETH9[ChainId.MOONRIVER], - USDC[ChainId.MOONRIVER], - USDT[ChainId.MOONRIVER], - DAI[ChainId.MOONRIVER], - FRAX[ChainId.MOONRIVER], - ], - [ChainId.FUSE]: [ - Native.onChain(ChainId.FUSE), - WNATIVE[ChainId.FUSE], - WBTC[ChainId.FUSE], - WETH9[ChainId.FUSE], - USDC[ChainId.FUSE], - USDT[ChainId.FUSE], - DAI[ChainId.FUSE], - ], - [ChainId.TELOS]: [ - Native.onChain(ChainId.TELOS), - WNATIVE[ChainId.TELOS], - WETH9[ChainId.TELOS], - USDC[ChainId.TELOS], - USDT[ChainId.TELOS], - ], - [ChainId.MOONBEAM]: [ - Native.onChain(ChainId.MOONBEAM), - WNATIVE[ChainId.MOONBEAM], - axlUSDC[ChainId.MOONBEAM], - WORMHOLE_USDC[ChainId.MOONBEAM], - WORMHOLE_WETH[ChainId.MOONBEAM], - WORMHOLE_WBTC[ChainId.MOONBEAM], - ], - [ChainId.OPTIMISM]: [ - Native.onChain(ChainId.OPTIMISM), - WNATIVE[ChainId.OPTIMISM], - WBTC[ChainId.OPTIMISM], - USDC[ChainId.OPTIMISM], - USDT[ChainId.OPTIMISM], - DAI[ChainId.OPTIMISM], - ], - [ChainId.KAVA]: [ - Native.onChain(ChainId.KAVA), - WNATIVE[ChainId.KAVA], - axlWBTC[ChainId.KAVA], - STARGATE_WETH[ChainId.KAVA], - axlUSDC[ChainId.KAVA], - USDT[ChainId.KAVA], - ], - [ChainId.METIS]: [ - Native.onChain(ChainId.METIS), - WNATIVE[ChainId.METIS], - WBTC[ChainId.METIS], - WETH9[ChainId.METIS], - USDC[ChainId.METIS], - USDT[ChainId.METIS], - DAI[ChainId.METIS], - ], - [ChainId.BOBA_AVAX]: [ - Native.onChain(ChainId.BOBA_AVAX), - WNATIVE[ChainId.BOBA_AVAX], - USDC[ChainId.BOBA_AVAX], - USDT[ChainId.BOBA_AVAX], - ], - [ChainId.BOBA_BNB]: [ - Native.onChain(ChainId.BOBA_BNB), - WNATIVE[ChainId.BOBA_BNB], - new Token({ - chainId: ChainId.BOBA_BNB, - symbol: 'BNB', - name: 'Binance Coin', - decimals: 18, - address: '0x4200000000000000000000000000000000000023', - }), - USDC[ChainId.BOBA_BNB], - USDT[ChainId.BOBA_BNB], - ], - [ChainId.BTTC]: [ - Native.onChain(ChainId.BTTC), - WNATIVE[ChainId.BTTC], - WETH9[ChainId.BTTC], - USDC[ChainId.BTTC], - USDT[ChainId.BTTC], - ], - // [ChainId.CONSENSUS_ZKEVM_TESTNET]: [ - // Native.onChain(ChainId.CONSENSUS_ZKEVM_TESTNET), - // WNATIVE[ChainId.CONSENSUS_ZKEVM_TESTNET], - // ], - // [ChainId.SCROLL_ALPHA_TESTNET]: [Native.onChain(ChainId.SCROLL_ALPHA_TESTNET), WNATIVE[ChainId.SCROLL_ALPHA_TESTNET]], - // [ChainId.BASE_TESTNET]: [Native.onChain(ChainId.BASE_TESTNET), WNATIVE[ChainId.BASE_TESTNET]], - [ChainId.POLYGON_ZKEVM]: [ - Native.onChain(ChainId.POLYGON_ZKEVM), - WNATIVE[ChainId.POLYGON_ZKEVM], - MATIC[ChainId.POLYGON_ZKEVM], - USDC[ChainId.POLYGON_ZKEVM], - USDT[ChainId.POLYGON_ZKEVM], - DAI[ChainId.POLYGON_ZKEVM], - WBTC[ChainId.POLYGON_ZKEVM], - ], - [ChainId.THUNDERCORE]: [ - Native.onChain(ChainId.THUNDERCORE), - WNATIVE[ChainId.THUNDERCORE], - WETH9[ChainId.THUNDERCORE], - USDC[ChainId.THUNDERCORE], - USDT[ChainId.THUNDERCORE], - WBTC[ChainId.THUNDERCORE], - ], - [ChainId.HAQQ]: [ - Native.onChain(ChainId.HAQQ), - WNATIVE[ChainId.HAQQ], - axlETH[ChainId.HAQQ], - axlWBTC[ChainId.HAQQ], - axlUSDC[ChainId.HAQQ], - axlUSDT[ChainId.HAQQ], - axlDAI[ChainId.HAQQ], - ], - [ChainId.CORE]: [ - Native.onChain(ChainId.CORE), - WNATIVE[ChainId.CORE], - WETH9[ChainId.CORE], - USDC[ChainId.CORE], - USDT[ChainId.CORE], - ], - [ChainId.ZKSYNC_ERA]: [ - Native.onChain(ChainId.ZKSYNC_ERA), - WNATIVE[ChainId.ZKSYNC_ERA], - WBTC[ChainId.ZKSYNC_ERA], - USDC[ChainId.ZKSYNC_ERA], - ], - [ChainId.LINEA]: [ - Native.onChain(ChainId.LINEA), - WNATIVE[ChainId.LINEA], - DAI[ChainId.LINEA], - USDC[ChainId.LINEA], - ], - [ChainId.BASE]: [ - Native.onChain(ChainId.BASE), - WNATIVE[ChainId.BASE], - DAI[ChainId.BASE], - new Token({ - chainId: ChainId.BASE, - symbol: 'USDbC', - name: 'USD Base Coin', - decimals: 6, - address: '0xd9aAEc86B65D86f6A7B5B1b0c42FFA531710b6CA', - }), - USDC[ChainId.BASE], - new Token({ - chainId: ChainId.BASE, - symbol: 'OX', - name: 'OX Coin', - decimals: 18, - address: '0xba0Dda8762C24dA9487f5FA026a9B64b695A07Ea', - }), - ], - [ChainId.SCROLL]: [ - Native.onChain(ChainId.SCROLL), - WNATIVE[ChainId.SCROLL], - USDC[ChainId.SCROLL], - USDT[ChainId.SCROLL], - WBTC[ChainId.SCROLL], - ], - [ChainId.FILECOIN]: [ - Native.onChain(ChainId.FILECOIN), - WNATIVE[ChainId.FILECOIN], - USDC[ChainId.FILECOIN], - DAI[ChainId.FILECOIN], - ], - [ChainId.ZETACHAIN]: [ - Native.onChain(ChainId.ZETACHAIN), - WNATIVE[ChainId.ZETACHAIN], - ZETA_ETH_BRIDGE_USDC, - ZETA_ETH_BRIDGE_USDT, - WETH9[ChainId.ZETACHAIN], - ], - [ChainId.CRONOS]: [ - Native.onChain(ChainId.CRONOS), - WNATIVE[ChainId.CRONOS], - WETH9[ChainId.CRONOS], - WBTC[ChainId.CRONOS], - USDC[ChainId.CRONOS], - ], - [ChainId.BLAST]: [Native.onChain(ChainId.BLAST), USDB[ChainId.BLAST]], - [ChainId.SKALE_EUROPA]: [ - SKL, - USDC[ChainId.SKALE_EUROPA], - WETH9[ChainId.SKALE_EUROPA], - ], - [ChainId.ROOTSTOCK]: [ - Native.onChain(ChainId.ROOTSTOCK), - WNATIVE[ChainId.ROOTSTOCK], - WETH9[ChainId.ROOTSTOCK], - USDT[ChainId.ROOTSTOCK], - ], - // [ChainId.SEPOLIA]: [Native.onChain(ChainId.SEPOLIA), WNATIVE[ChainId.SEPOLIA]], -} as const satisfies Record> - -// const DEFAULT_BASES_IDS = Object.entries(DEFAULT_BASES).reduce< -// Record -// >((acc, [chain, tokens]) => { -// const chainId = chain -// acc[chainId] = Array.from(new Set(tokens.map((token) => token.id))) -// return acc -// }, {} as Record) - function getAddress(address: string) { if (address === 'NATIVE') return 'NATIVE' return _getAddress(address) diff --git a/packages/sushi/src/config/default-bases.ts b/packages/sushi/src/config/default-bases.ts new file mode 100644 index 0000000000..b8156daf0e --- /dev/null +++ b/packages/sushi/src/config/default-bases.ts @@ -0,0 +1,381 @@ +import { getAddress as _getAddress } from 'viem/utils' +import { ChainId } from '../chain/index.js' +import { + STARGATE_USDC, + STARGATE_USDT, + STARGATE_WBTC, + STARGATE_WETH, +} from '../config/index.js' +import { + ARB, + DAI, + FRAX, + GNO, + MATIC, + MIM, + SKL, + SUSHI, + USDB, + USDC, + USDT, + WBTC, + WETH9, + WNATIVE, + WORMHOLE_USDC, + WORMHOLE_WBTC, + WORMHOLE_WETH, + ZETA_ETH_BRIDGE_USDC, + ZETA_ETH_BRIDGE_USDT, + axlDAI, + axlETH, + axlUSDC, + axlUSDT, + axlWBTC, +} from '../currency/index.js' +import { Native, Token } from '../currency/index.js' + +/* + Currencies that are shown at the top of the token selector by default +*/ +export const DEFAULT_BASES = { + [ChainId.ETHEREUM]: [ + Native.onChain(ChainId.ETHEREUM), + WNATIVE[ChainId.ETHEREUM], + SUSHI[ChainId.ETHEREUM], + WBTC[ChainId.ETHEREUM], + USDC[ChainId.ETHEREUM], + USDT[ChainId.ETHEREUM], + DAI[ChainId.ETHEREUM], + ], + [ChainId.SEPOLIA]: [ + Native.onChain(ChainId.SEPOLIA), + WNATIVE[ChainId.SEPOLIA], + USDC[ChainId.SEPOLIA], + ], + // [ChainId.ROPSTEN]: [], + // [ChainId.RINKEBY]: [], + // [ChainId.GÖRLI]: [], + // [ChainId.KOVAN]: [], + [ChainId.GNOSIS]: [ + Native.onChain(ChainId.GNOSIS), + WNATIVE[ChainId.GNOSIS], + GNO[ChainId.GNOSIS], + WETH9[ChainId.GNOSIS], + USDC[ChainId.GNOSIS], + USDT[ChainId.GNOSIS], + DAI[ChainId.GNOSIS], + ], + [ChainId.BSC]: [ + Native.onChain(ChainId.BSC), + WNATIVE[ChainId.BSC], + WETH9[ChainId.BSC], + USDC[ChainId.BSC], + USDT[ChainId.BSC], + DAI[ChainId.BSC], + ], + [ChainId.BSC_TESTNET]: [], + [ChainId.POLYGON]: [ + Native.onChain(ChainId.POLYGON), + WNATIVE[ChainId.POLYGON], + WBTC[ChainId.POLYGON], + WETH9[ChainId.POLYGON], + USDC[ChainId.POLYGON], + USDT[ChainId.POLYGON], + DAI[ChainId.POLYGON], + ], + [ChainId.POLYGON_TESTNET]: [], + [ChainId.AVALANCHE]: [ + Native.onChain(ChainId.AVALANCHE), + WNATIVE[ChainId.AVALANCHE], + WETH9[ChainId.AVALANCHE], + WBTC[ChainId.AVALANCHE], + USDC[ChainId.AVALANCHE], + USDT[ChainId.AVALANCHE], + DAI[ChainId.AVALANCHE], + MIM[ChainId.AVALANCHE], + FRAX[ChainId.AVALANCHE], + ], + [ChainId.AVALANCHE_TESTNET]: [], + [ChainId.ARBITRUM_NOVA]: [ + Native.onChain(ChainId.ARBITRUM_NOVA), + WNATIVE[ChainId.ARBITRUM_NOVA], + ARB[ChainId.ARBITRUM_NOVA], + WBTC[ChainId.ARBITRUM_NOVA], + USDC[ChainId.ARBITRUM_NOVA], + USDT[ChainId.ARBITRUM_NOVA], + DAI[ChainId.ARBITRUM_NOVA], + ], + [ChainId.BOBA]: [ + Native.onChain(ChainId.BOBA), + WNATIVE[ChainId.BOBA], + USDC[ChainId.BOBA], + USDT[ChainId.BOBA], + DAI[ChainId.BOBA], + FRAX[ChainId.BOBA], + WBTC[ChainId.BOBA], + ], + [ChainId.FANTOM]: [ + Native.onChain(ChainId.FANTOM), + WNATIVE[ChainId.FANTOM], + axlUSDC[ChainId.FANTOM], + STARGATE_USDC[ChainId.FANTOM], + STARGATE_USDT[ChainId.FANTOM], + STARGATE_WETH[ChainId.FANTOM], + STARGATE_WBTC[ChainId.FANTOM], + axlUSDC[ChainId.FANTOM], + MIM[ChainId.FANTOM], + ], + [ChainId.FANTOM_TESTNET]: [], + [ChainId.ARBITRUM]: [ + Native.onChain(ChainId.ARBITRUM), + WNATIVE[ChainId.ARBITRUM], + ARB[ChainId.ARBITRUM], + WBTC[ChainId.ARBITRUM], + USDC[ChainId.ARBITRUM], + USDT[ChainId.ARBITRUM], + DAI[ChainId.ARBITRUM], + MIM[ChainId.ARBITRUM], + ], + [ChainId.ARBITRUM_TESTNET]: [], + [ChainId.HARMONY]: [ + Native.onChain(ChainId.HARMONY), + WNATIVE[ChainId.HARMONY], + WETH9[ChainId.HARMONY], + USDC[ChainId.HARMONY], + USDT[ChainId.HARMONY], + DAI[ChainId.HARMONY], + ], + // [ChainId.HARMONY_TESTNET]: [], + [ChainId.HECO]: [ + Native.onChain(ChainId.HECO), + WNATIVE[ChainId.HECO], + WETH9[ChainId.HECO], + USDC[ChainId.HECO], + USDT[ChainId.HECO], + DAI[ChainId.HECO], + ], + // [ChainId.HECO_TESTNET]: [], + [ChainId.OKEX]: [ + Native.onChain(ChainId.OKEX), + WNATIVE[ChainId.OKEX], + WETH9[ChainId.OKEX], + USDC[ChainId.OKEX], + USDT[ChainId.OKEX], + DAI[ChainId.OKEX], + ], + // [ChainId.OKEX_TESTNET]: [], + [ChainId.CELO]: [ + Native.onChain(ChainId.CELO), + // WNATIVE[ChainId.CELO], + WETH9[ChainId.CELO], + USDC[ChainId.CELO], + USDT[ChainId.CELO], + DAI[ChainId.CELO], + ], + [ChainId.PALM]: [ + Native.onChain(ChainId.PALM), + WNATIVE[ChainId.PALM], + WETH9[ChainId.PALM], + ], + [ChainId.MOONRIVER]: [ + Native.onChain(ChainId.MOONRIVER), + WNATIVE[ChainId.MOONRIVER], + WETH9[ChainId.MOONRIVER], + USDC[ChainId.MOONRIVER], + USDT[ChainId.MOONRIVER], + DAI[ChainId.MOONRIVER], + FRAX[ChainId.MOONRIVER], + ], + [ChainId.FUSE]: [ + Native.onChain(ChainId.FUSE), + WNATIVE[ChainId.FUSE], + WBTC[ChainId.FUSE], + WETH9[ChainId.FUSE], + USDC[ChainId.FUSE], + USDT[ChainId.FUSE], + DAI[ChainId.FUSE], + ], + [ChainId.TELOS]: [ + Native.onChain(ChainId.TELOS), + WNATIVE[ChainId.TELOS], + WETH9[ChainId.TELOS], + USDC[ChainId.TELOS], + USDT[ChainId.TELOS], + ], + [ChainId.MOONBEAM]: [ + Native.onChain(ChainId.MOONBEAM), + WNATIVE[ChainId.MOONBEAM], + axlUSDC[ChainId.MOONBEAM], + WORMHOLE_USDC[ChainId.MOONBEAM], + WORMHOLE_WETH[ChainId.MOONBEAM], + WORMHOLE_WBTC[ChainId.MOONBEAM], + ], + [ChainId.OPTIMISM]: [ + Native.onChain(ChainId.OPTIMISM), + WNATIVE[ChainId.OPTIMISM], + WBTC[ChainId.OPTIMISM], + USDC[ChainId.OPTIMISM], + USDT[ChainId.OPTIMISM], + DAI[ChainId.OPTIMISM], + ], + [ChainId.KAVA]: [ + Native.onChain(ChainId.KAVA), + WNATIVE[ChainId.KAVA], + axlWBTC[ChainId.KAVA], + STARGATE_WETH[ChainId.KAVA], + axlUSDC[ChainId.KAVA], + USDT[ChainId.KAVA], + ], + [ChainId.METIS]: [ + Native.onChain(ChainId.METIS), + WNATIVE[ChainId.METIS], + WBTC[ChainId.METIS], + WETH9[ChainId.METIS], + USDC[ChainId.METIS], + USDT[ChainId.METIS], + DAI[ChainId.METIS], + ], + [ChainId.BOBA_AVAX]: [ + Native.onChain(ChainId.BOBA_AVAX), + WNATIVE[ChainId.BOBA_AVAX], + USDC[ChainId.BOBA_AVAX], + USDT[ChainId.BOBA_AVAX], + ], + [ChainId.BOBA_BNB]: [ + Native.onChain(ChainId.BOBA_BNB), + WNATIVE[ChainId.BOBA_BNB], + new Token({ + chainId: ChainId.BOBA_BNB, + symbol: 'BNB', + name: 'Binance Coin', + decimals: 18, + address: '0x4200000000000000000000000000000000000023', + }), + USDC[ChainId.BOBA_BNB], + USDT[ChainId.BOBA_BNB], + ], + [ChainId.BTTC]: [ + Native.onChain(ChainId.BTTC), + WNATIVE[ChainId.BTTC], + WETH9[ChainId.BTTC], + USDC[ChainId.BTTC], + USDT[ChainId.BTTC], + ], + // [ChainId.CONSENSUS_ZKEVM_TESTNET]: [ + // Native.onChain(ChainId.CONSENSUS_ZKEVM_TESTNET), + // WNATIVE[ChainId.CONSENSUS_ZKEVM_TESTNET], + // ], + // [ChainId.SCROLL_ALPHA_TESTNET]: [Native.onChain(ChainId.SCROLL_ALPHA_TESTNET), WNATIVE[ChainId.SCROLL_ALPHA_TESTNET]], + // [ChainId.BASE_TESTNET]: [Native.onChain(ChainId.BASE_TESTNET), WNATIVE[ChainId.BASE_TESTNET]], + [ChainId.POLYGON_ZKEVM]: [ + Native.onChain(ChainId.POLYGON_ZKEVM), + WNATIVE[ChainId.POLYGON_ZKEVM], + MATIC[ChainId.POLYGON_ZKEVM], + USDC[ChainId.POLYGON_ZKEVM], + USDT[ChainId.POLYGON_ZKEVM], + DAI[ChainId.POLYGON_ZKEVM], + WBTC[ChainId.POLYGON_ZKEVM], + ], + [ChainId.THUNDERCORE]: [ + Native.onChain(ChainId.THUNDERCORE), + WNATIVE[ChainId.THUNDERCORE], + WETH9[ChainId.THUNDERCORE], + USDC[ChainId.THUNDERCORE], + USDT[ChainId.THUNDERCORE], + WBTC[ChainId.THUNDERCORE], + ], + [ChainId.HAQQ]: [ + Native.onChain(ChainId.HAQQ), + WNATIVE[ChainId.HAQQ], + axlETH[ChainId.HAQQ], + axlWBTC[ChainId.HAQQ], + axlUSDC[ChainId.HAQQ], + axlUSDT[ChainId.HAQQ], + axlDAI[ChainId.HAQQ], + ], + [ChainId.CORE]: [ + Native.onChain(ChainId.CORE), + WNATIVE[ChainId.CORE], + WETH9[ChainId.CORE], + USDC[ChainId.CORE], + USDT[ChainId.CORE], + ], + [ChainId.ZKSYNC_ERA]: [ + Native.onChain(ChainId.ZKSYNC_ERA), + WNATIVE[ChainId.ZKSYNC_ERA], + WBTC[ChainId.ZKSYNC_ERA], + USDC[ChainId.ZKSYNC_ERA], + ], + [ChainId.LINEA]: [ + Native.onChain(ChainId.LINEA), + WNATIVE[ChainId.LINEA], + DAI[ChainId.LINEA], + USDC[ChainId.LINEA], + ], + [ChainId.BASE]: [ + Native.onChain(ChainId.BASE), + WNATIVE[ChainId.BASE], + DAI[ChainId.BASE], + new Token({ + chainId: ChainId.BASE, + symbol: 'USDbC', + name: 'USD Base Coin', + decimals: 6, + address: '0xd9aAEc86B65D86f6A7B5B1b0c42FFA531710b6CA', + }), + USDC[ChainId.BASE], + new Token({ + chainId: ChainId.BASE, + symbol: 'OX', + name: 'OX Coin', + decimals: 18, + address: '0xba0Dda8762C24dA9487f5FA026a9B64b695A07Ea', + }), + ], + [ChainId.SCROLL]: [ + Native.onChain(ChainId.SCROLL), + WNATIVE[ChainId.SCROLL], + USDC[ChainId.SCROLL], + USDT[ChainId.SCROLL], + WBTC[ChainId.SCROLL], + ], + [ChainId.FILECOIN]: [ + Native.onChain(ChainId.FILECOIN), + WNATIVE[ChainId.FILECOIN], + USDC[ChainId.FILECOIN], + DAI[ChainId.FILECOIN], + ], + [ChainId.ZETACHAIN]: [ + Native.onChain(ChainId.ZETACHAIN), + WNATIVE[ChainId.ZETACHAIN], + ZETA_ETH_BRIDGE_USDC, + ZETA_ETH_BRIDGE_USDT, + WETH9[ChainId.ZETACHAIN], + ], + [ChainId.CRONOS]: [ + Native.onChain(ChainId.CRONOS), + WNATIVE[ChainId.CRONOS], + WETH9[ChainId.CRONOS], + WBTC[ChainId.CRONOS], + USDC[ChainId.CRONOS], + ], + [ChainId.BLAST]: [Native.onChain(ChainId.BLAST), USDB[ChainId.BLAST]], + [ChainId.SKALE_EUROPA]: [ + SKL, + USDC[ChainId.SKALE_EUROPA], + WETH9[ChainId.SKALE_EUROPA], + ], + [ChainId.ROOTSTOCK]: [ + Native.onChain(ChainId.ROOTSTOCK), + WNATIVE[ChainId.ROOTSTOCK], + WETH9[ChainId.ROOTSTOCK], + USDT[ChainId.ROOTSTOCK], + ], + // [ChainId.SEPOLIA]: [Native.onChain(ChainId.SEPOLIA), WNATIVE[ChainId.SEPOLIA]], +} as const satisfies Record> + +// const DEFAULT_BASES_IDS = Object.entries(DEFAULT_BASES).reduce< +// Record +// >((acc, [chain, tokens]) => { +// const chainId = chain +// acc[chainId] = Array.from(new Set(tokens.map((token) diff --git a/packages/sushi/src/config/index.ts b/packages/sushi/src/config/index.ts index a7520831de..d4add5774f 100644 --- a/packages/sushi/src/config/index.ts +++ b/packages/sushi/src/config/index.ts @@ -4,6 +4,7 @@ export * from './api.js' export * from './bases-to-check-trades-against.js' export * from './bentobox.js' export * from './custom-bases.js' +export * from './default-bases.js' export * from './default-quote.js' export * from './furo.js' export * from './default-slippage.js' From 4b0b76109cb5e603b05e7215b9f8013ad3178e36 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Fri, 9 Aug 2024 15:05:30 +0100 Subject: [PATCH 104/125] fix: swap test speed --- apps/web/test/helpers/swap.ts | 160 ++++++------------ apps/web/test/playwright.config.ts | 3 +- apps/web/test/swap/simple.test.ts | 26 ++- packages/sushi/src/config/default-bases.ts | 15 +- .../pool/sushiswap-v2/sushiswap-v2-pool.ts | 2 +- .../NonfungiblePositionManager.test.ts | 5 +- .../sushiswap-v3/entities/Position.test.ts | 5 +- .../entities/SushiSwapV3Pool.test.ts | 5 +- .../trident-constant-pool.test.ts | 2 +- .../trident-stable-pool.test.ts | 2 +- packages/sushi/test/tines/snapshots/report | 21 +-- pnpm-lock.yaml | 4 + 12 files changed, 98 insertions(+), 152 deletions(-) diff --git a/apps/web/test/helpers/swap.ts b/apps/web/test/helpers/swap.ts index 364f99fcfb..87f04755e6 100644 --- a/apps/web/test/helpers/swap.ts +++ b/apps/web/test/helpers/swap.ts @@ -1,6 +1,6 @@ import { Page, expect } from '@playwright/test' import { API_BASE_URL } from 'sushi/config' -import { Native, Type } from 'sushi/currency' +import { Amount, Native, Type } from 'sushi/currency' import { zeroAddress } from 'viem' import { BaseActions } from './base' // Adjust the import path as necessary @@ -19,7 +19,11 @@ export class SwapPage extends BaseActions { await this.page.goto(url) } - async wrap(inputCurrency: Type, outputCurrency: Type, amount: string) { + async wrap( + inputCurrency: Type, + outputCurrency: Type, + amount: Amount | 'max', + ) { await this.handleToken(inputCurrency, 'INPUT') await this.handleToken(outputCurrency, 'OUTPUT') await this.inputAmount(amount) @@ -81,101 +85,27 @@ export class SwapPage extends BaseActions { await makeAnotherSwap.click() } - async swap(inputCurrency: Type, outputCurrency: Type, amount: string) { + async swap( + inputCurrency: Type, + outputCurrency: Type, + amount: Amount | 'max', + ) { await this.handleToken(inputCurrency, 'INPUT') await this.handleToken(outputCurrency, 'OUTPUT') await this.inputAmount(amount) - const swapFromBalance = this.page.locator( - '[testdata-id=swap-from-balance-button]', - ) - await expect(swapFromBalance).toBeVisible() - await expect(swapFromBalance).toBeEnabled() - const swapFromBalanceBefore = await swapFromBalance.textContent() - - const swapToBalance = this.page.locator( - '[testdata-id=swap-to-balance-button]', - ) - await expect(swapToBalance).toBeVisible() - const swapToBalanceBefore = await swapToBalance.textContent() - - await this.approve(inputCurrency) - - const swapButton = this.page.locator('[testdata-id=swap-button]') - await expect(swapButton).toBeVisible() - - // const priceImpactCheckbox = page.locator( - // '[testdata-id=price-impact-checkbox]', + // const swapFromBalance = this.page.locator( + // '[testdata-id=swap-from-balance-button]', // ) - // while (!(await swapButton.isEnabled())) { - // if ( - // (await priceImpactCheckbox.isVisible()) && - // !(await priceImpactCheckbox.isChecked()) - // ) { - // await priceImpactCheckbox.check() - // } - // } - - await swapButton.isEnabled() - - await swapButton.click() - - const confirmSwap = this.page.locator('[testdata-id=confirm-swap-button]') - // const confirmSwap = page.getByRole('button', { name: `Swap ${inputCurrency.symbol} for ${outputCurrency.symbol}` }) - await expect(confirmSwap).toBeVisible() - await expect(confirmSwap).toBeEnabled() - await confirmSwap.click() - - // If this text is duplicated elsewhere it could false positive - const expectedSwappingText = new RegExp( - `(Swapping .* ${inputCurrency.symbol}.* for .* ${outputCurrency.symbol}.*.)`, - ) - expect(this.page.getByText(expectedSwappingText)).toBeVisible() - - // If this text is duplicated elsewhere it could false positive - const expectedSwapText = new RegExp( - `(Swap .* ${inputCurrency.symbol}.* for .* ${outputCurrency.symbol}.*.)`, - ) - expect(this.page.getByText(expectedSwapText)).toBeVisible() + // await expect(swapFromBalance).toBeVisible() + // await expect(swapFromBalance).toBeEnabled() + // const swapFromBalanceBefore = await swapFromBalance.textContent() - // Make another swap - const makeAnotherSwap = this.page.locator( - '[testdata-id=make-another-swap-button]', - ) - await expect(makeAnotherSwap).toBeVisible() - await expect(makeAnotherSwap).toBeEnabled() - await makeAnotherSwap.click() - - // Compare against cached balances to ensure there is at least a change... - await expect(swapFromBalance).not.toHaveText( - swapFromBalanceBefore as string, - ) - const swapFromBalanceAfter = await swapFromBalance.textContent() - expect(swapFromBalanceBefore).not.toEqual(swapFromBalanceAfter) - - await expect(swapToBalance).not.toHaveText(swapToBalanceBefore as string) - const swapToBalanceAfter = await swapToBalance.textContent() - expect(swapToBalanceBefore).not.toEqual(swapToBalanceAfter) - } - - async maxSwap(inputCurrency: Type, outputCurrency: Type) { - await this.handleToken(inputCurrency, 'INPUT') - await this.handleToken(outputCurrency, 'OUTPUT') - - await this.maxInput(this.page) - - // Cache balances before swap - const swapFromBalance = this.page.locator( - '[testdata-id=swap-from-balance-button]', - ) - await expect(swapFromBalance).toBeVisible() - await expect(swapFromBalance).toBeEnabled() - const swapFromBalanceBefore = await swapFromBalance.textContent() - const swapToBalance = this.page.locator( - '[testdata-id=swap-to-balance-button]', - ) - await expect(swapToBalance).toBeVisible() - const swapToBalanceBefore = await swapToBalance.textContent() + // const swapToBalance = this.page.locator( + // '[testdata-id=swap-to-balance-button]', + // ) + // await expect(swapToBalance).toBeVisible() + // const swapToBalanceBefore = await swapToBalance.textContent() await this.approve(inputCurrency) @@ -194,7 +124,8 @@ export class SwapPage extends BaseActions { } } - await expect(swapButton).toBeEnabled() + await swapButton.isEnabled() + await swapButton.click() const confirmSwap = this.page.locator('[testdata-id=confirm-swap-button]') @@ -203,11 +134,13 @@ export class SwapPage extends BaseActions { await expect(confirmSwap).toBeEnabled() await confirmSwap.click() + // If this text is duplicated elsewhere it could false positive const expectedSwappingText = new RegExp( `(Swapping .* ${inputCurrency.symbol}.* for .* ${outputCurrency.symbol}.*.)`, ) expect(this.page.getByText(expectedSwappingText)).toBeVisible() + // If this text is duplicated elsewhere it could false positive const expectedSwapText = new RegExp( `(Swap .* ${inputCurrency.symbol}.* for .* ${outputCurrency.symbol}.*.)`, ) @@ -222,15 +155,15 @@ export class SwapPage extends BaseActions { await makeAnotherSwap.click() // Compare against cached balances to ensure there is at least a change... - await expect(swapFromBalance).not.toHaveText( - swapFromBalanceBefore as string, - ) - const swapFromBalanceAfter = await swapFromBalance.textContent() - expect(swapFromBalanceBefore).not.toEqual(swapFromBalanceAfter) + // await expect(swapFromBalance).not.toHaveText( + // swapFromBalanceBefore as string, + // ) + // const swapFromBalanceAfter = await swapFromBalance.textContent() + // expect(swapFromBalanceBefore).not.toEqual(swapFromBalanceAfter) - await expect(swapToBalance).not.toHaveText(swapToBalanceBefore as string) - const swapToBalanceAfter = await swapToBalance.textContent() - expect(swapToBalanceBefore).not.toEqual(swapToBalanceAfter) + // await expect(swapToBalance).not.toHaveText(swapToBalanceBefore as string) + // const swapToBalanceAfter = await swapToBalance.textContent() + // expect(swapToBalanceBefore).not.toEqual(swapToBalanceAfter) } async approve(currency: Type) { @@ -285,19 +218,30 @@ export class SwapPage extends BaseActions { await expect(tokenSelector).toContainText(currency.symbol as string) } - async maxInput(page: Page) { - const maxButton = page.locator('[testdata-id=swap-from-balance-button]') + async maxInput() { + const maxButton = this.page.locator( + '[testdata-id=swap-from-balance-button]', + ) await expect(maxButton).toBeVisible() await expect(maxButton).toBeEnabled() await maxButton.click() } - async inputAmount(amount: string) { - const input0 = this.page.locator('[testdata-id=swap-from-input]') - // Inputs are not rendered until the trade is found - await expect(input0).toBeVisible() - await expect(input0).toBeEnabled() - await input0.fill(amount) + async inputAmount(amount: Amount | 'max') { + if (amount === 'max') { + const maxButton = this.page.locator( + '[testdata-id=swap-from-balance-button]', + ) + await expect(maxButton).toBeVisible() + await expect(maxButton).toBeEnabled() + await maxButton.click() + } else { + const input0 = this.page.locator('[testdata-id=swap-from-input]') + // Inputs are not rendered until the trade is found + await expect(input0).toBeVisible() + await expect(input0).toBeEnabled() + await input0.fill(amount.toExact()) + } } async mockSwapApi(jsonFile: string) { diff --git a/apps/web/test/playwright.config.ts b/apps/web/test/playwright.config.ts index f0559b5c95..d559fc4aee 100644 --- a/apps/web/test/playwright.config.ts +++ b/apps/web/test/playwright.config.ts @@ -18,7 +18,8 @@ const baseURL = `http://localhost:${PORT}` * See https://playwright.dev/docs/test-configuration. */ const config: PlaywrightTestConfig = { - quiet: !!process.env.CI, + // quiet: !!process.env.CI, + quiet: true, testMatch: [ 'simple.test.ts', 'pool.test.ts', diff --git a/apps/web/test/swap/simple.test.ts b/apps/web/test/swap/simple.test.ts index 3598fe2955..fa139cb6b1 100644 --- a/apps/web/test/swap/simple.test.ts +++ b/apps/web/test/swap/simple.test.ts @@ -64,60 +64,56 @@ test.beforeEach(async ({ page, next }) => { }) test('Wrap and unwrap', async ({ page }) => { - // test.slow() + test.slow() const swapPage = new SwapPage(page, chainId) await swapPage.goTo(url) await swapPage.connect() await swapPage.switchNetwork(chainId) await swapPage.mockSwapApi(`test/swap/mock/${chainId}-wrap.json`) - await swapPage.wrap(native, wnative, nativeAmount.toExact()) - + await swapPage.wrap(native, wnative, nativeAmount) await swapPage.mockSwapApi(`test/swap/mock/${chainId}-unwrap.json`) - await swapPage.wrap(wnative, native, nativeAmount.toExact()) + await swapPage.wrap(wnative, native, 'max') }) test('swap Native to USDC, then USDC to NATIVE', async ({ page }) => { - // test.slow() const swapPage = new SwapPage(page, chainId) await swapPage.goTo(url) await swapPage.connect() await swapPage.switchNetwork(chainId) await swapPage.mockSwapApi(`test/swap/mock/${chainId}-native-to-usdc.json`) - await swapPage.swap(native, usdc, nativeAmount.toExact()) + await swapPage.swap(native, usdc, nativeAmount) await swapPage.mockSwapApi(`test/swap/mock/${chainId}-usdc-to-native.json`) - await swapPage.maxSwap(usdc, native) + await swapPage.swap(usdc, native, 'max') }) test('swap Native to USDT, then USDT to NATIVE', async ({ page }) => { - // test.slow() const swapPage = new SwapPage(page, chainId) await swapPage.goTo(url) await swapPage.connect() await swapPage.switchNetwork(chainId) await swapPage.mockSwapApi(`test/swap/mock/${chainId}-native-to-usdt.json`) - await swapPage.swap(native, usdt, nativeAmount.toExact()) + await swapPage.swap(native, usdt, nativeAmount) await swapPage.mockSwapApi(`test/swap/mock/${chainId}-usdt-to-native.json`) - await swapPage.maxSwap(usdt, native) + await swapPage.swap(usdt, native, 'max') }) test('Swap Native to USDC, USDC to USDT then USDT to NATIVE', async ({ page, }) => { - // test.slow() const swapPage = new SwapPage(page, chainId) await swapPage.goTo(url) await swapPage.connect() await swapPage.switchNetwork(chainId) await swapPage.mockSwapApi(`test/swap/mock/${chainId}-native-to-usdc.json`) - await swapPage.swap(native, usdc, nativeAmount.toExact()) + await swapPage.swap(native, usdc, nativeAmount) await swapPage.mockSwapApi(`test/swap/mock/${chainId}-usdc-to-usdt.json`) - await swapPage.maxSwap(usdc, usdt) + await swapPage.swap(usdc, usdt, 'max') await swapPage.mockSwapApi(`test/swap/mock/${chainId}-usdt-to-native.json`) - await swapPage.maxSwap(usdt, native) + await swapPage.swap(usdt, native, 'max') }) test('Swap Native to WBTC', async ({ page }) => { @@ -128,5 +124,5 @@ test('Swap Native to WBTC', async ({ page }) => { await swapPage.switchNetwork(chainId) await swapPage.mockSwapApi(`test/swap/mock/${chainId}-native-to-wbtc.json`) - await swapPage.swap(native, wbtc, nativeAmount.toExact()) + await swapPage.swap(native, wbtc, nativeAmount) }) diff --git a/packages/sushi/src/config/default-bases.ts b/packages/sushi/src/config/default-bases.ts index b8156daf0e..3e30fd33b1 100644 --- a/packages/sushi/src/config/default-bases.ts +++ b/packages/sushi/src/config/default-bases.ts @@ -1,11 +1,5 @@ import { getAddress as _getAddress } from 'viem/utils' import { ChainId } from '../chain/index.js' -import { - STARGATE_USDC, - STARGATE_USDT, - STARGATE_WBTC, - STARGATE_WETH, -} from '../config/index.js' import { ARB, DAI, @@ -13,8 +7,10 @@ import { GNO, MATIC, MIM, + Native, SKL, SUSHI, + Token, USDB, USDC, USDT, @@ -32,7 +28,12 @@ import { axlUSDT, axlWBTC, } from '../currency/index.js' -import { Native, Token } from '../currency/index.js' +import { + STARGATE_USDC, + STARGATE_USDT, + STARGATE_WBTC, + STARGATE_WETH, +} from './stargate.js' /* Currencies that are shown at the top of the token selector by default diff --git a/packages/sushi/src/pool/sushiswap-v2/sushiswap-v2-pool.ts b/packages/sushi/src/pool/sushiswap-v2/sushiswap-v2-pool.ts index cad1eb1a2b..419b69e1cd 100644 --- a/packages/sushi/src/pool/sushiswap-v2/sushiswap-v2-pool.ts +++ b/packages/sushi/src/pool/sushiswap-v2/sushiswap-v2-pool.ts @@ -3,7 +3,7 @@ import { chainName } from '../../chain/index.js' import { SUSHISWAP_V2_FACTORY_ADDRESS, isSushiSwapV2ChainId, -} from '../../config/index.js' +} from '../../config/sushiswap-v2.js' import { Amount, Price, Token } from '../../currency/index.js' import { InsufficientInputAmountError, diff --git a/packages/sushi/src/pool/sushiswap-v3/entities/NonfungiblePositionManager.test.ts b/packages/sushi/src/pool/sushiswap-v3/entities/NonfungiblePositionManager.test.ts index db42f4fece..c35bd99f32 100644 --- a/packages/sushi/src/pool/sushiswap-v3/entities/NonfungiblePositionManager.test.ts +++ b/packages/sushi/src/pool/sushiswap-v3/entities/NonfungiblePositionManager.test.ts @@ -1,5 +1,8 @@ import { describe, expect, it } from 'vitest' -import { SushiSwapV3FeeAmount, TICK_SPACINGS } from '../../../config/index.js' +import { + SushiSwapV3FeeAmount, + TICK_SPACINGS, +} from '../../../config/sushiswap-v3.js' import { Amount as CurrencyAmount, Native, diff --git a/packages/sushi/src/pool/sushiswap-v3/entities/Position.test.ts b/packages/sushi/src/pool/sushiswap-v3/entities/Position.test.ts index ef8cc8ffca..fecf50f561 100644 --- a/packages/sushi/src/pool/sushiswap-v3/entities/Position.test.ts +++ b/packages/sushi/src/pool/sushiswap-v3/entities/Position.test.ts @@ -1,5 +1,8 @@ import { describe, expect, it } from 'vitest' -import { SushiSwapV3FeeAmount, TICK_SPACINGS } from '../../../config/index.js' +import { + SushiSwapV3FeeAmount, + TICK_SPACINGS, +} from '../../../config/sushiswap-v3.js' import { Token } from '../../../currency/index.js' import { Percent } from '../../../math/index.js' import { encodeSqrtRatioX96 } from '../utils/encodeSqrtRatioX96.js' diff --git a/packages/sushi/src/pool/sushiswap-v3/entities/SushiSwapV3Pool.test.ts b/packages/sushi/src/pool/sushiswap-v3/entities/SushiSwapV3Pool.test.ts index 71fe557017..7037a6ce58 100644 --- a/packages/sushi/src/pool/sushiswap-v3/entities/SushiSwapV3Pool.test.ts +++ b/packages/sushi/src/pool/sushiswap-v3/entities/SushiSwapV3Pool.test.ts @@ -1,5 +1,8 @@ import { beforeEach, describe, expect, it } from 'vitest' -import { SushiSwapV3FeeAmount, TICK_SPACINGS } from '../../../config/index.js' +import { + SushiSwapV3FeeAmount, + TICK_SPACINGS, +} from '../../../config/sushiswap-v3.js' import { Amount as CurrencyAmount, Token, diff --git a/packages/sushi/src/pool/trident-constant-product/trident-constant-pool.test.ts b/packages/sushi/src/pool/trident-constant-product/trident-constant-pool.test.ts index 2242d6477f..4349bd9589 100644 --- a/packages/sushi/src/pool/trident-constant-product/trident-constant-pool.test.ts +++ b/packages/sushi/src/pool/trident-constant-product/trident-constant-pool.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from 'vitest' import { ChainId } from '../../chain/index.js' -import { TRIDENT_CONSTANT_POOL_FACTORY_ADDRESS } from '../../config/index.js' +import { TRIDENT_CONSTANT_POOL_FACTORY_ADDRESS } from '../../config/trident.js' import { Amount, Price, diff --git a/packages/sushi/src/pool/trident-stable/trident-stable-pool.test.ts b/packages/sushi/src/pool/trident-stable/trident-stable-pool.test.ts index 7b40e26e76..5639908e16 100644 --- a/packages/sushi/src/pool/trident-stable/trident-stable-pool.test.ts +++ b/packages/sushi/src/pool/trident-stable/trident-stable-pool.test.ts @@ -1,6 +1,6 @@ import { describe, expect, it } from 'vitest' import { ChainId } from '../../chain/index.js' -import { TRIDENT_STABLE_POOL_FACTORY_ADDRESS } from '../../config/index.js' +import { TRIDENT_STABLE_POOL_FACTORY_ADDRESS } from '../../config/trident.js' import { Amount, Price, diff --git a/packages/sushi/test/tines/snapshots/report b/packages/sushi/test/tines/snapshots/report index 6d24e5f0ff..811a390761 100644 --- a/packages/sushi/test/tines/snapshots/report +++ b/packages/sushi/test/tines/snapshots/report @@ -1,17 +1,5 @@ 1:"top20-0": 5.999999993733542 -> 5.999999993733542 (0%) avg:0% -4:"bridge-4": 5496.94 -> 5496.94 (0%) avg:0% -5:"bridge-5-1": 4260.964 -> 4260.964 (0%) avg:0% -6:"bridge-5-2": 5473.94 -> 5473.94 (0%) avg:0% -7:"bridge-5-3": 5501.94 -> 5501.94 (0%) avg:0% -8:"bridge-5-5": 5528.94 -> 5528.94 (0%) avg:0% -9:"bridge-5-10": 5528.94 -> 5528.94 (0%) avg:0% -10:"bridge-5-30": 5528.94 -> 5528.94 (0%) avg:0% -11:"bridge-5-100": 5528.94 -> 5528.94 (0%) avg:0% -12:"bridge-5-300": 5528.94 -> 5528.94 (0%) avg:0% 2:"top20-1": 1.1195509365387262e+37 -> 1.1195509365387262e+37 (0%) avg:0% -3:"top20-2": 96249232830474440000 -> 96249232830474440000 (0%) avg:0% -4:"top20-3": 467011582838851800000 -> 467011582838851800000 (0%) avg:0% -5:"top20-4": 14263706377454.916 -> 14263706377454.916 (0%) avg:0% 13:"bridge-5-1000": 5528.94 -> 5528.94 (0%) avg:0% 14:"bridge-6": 579.9911997249991 -> 579.9911997249991 (0%) avg:0% 15:"bridge-7-1": 567.9947198349995 -> 567.9947198349995 (0%) avg:0% @@ -20,13 +8,17 @@ 18:"bridge-7-5": 577.9911997249991 -> 577.9911997249991 (0%) avg:0% 19:"bridge-7-10": 579.9911997249991 -> 579.9911997249991 (0%) avg:0% 20:"bridge-7-30": 579.9911997249991 -> 579.9911997249991 (0%) avg:0% +3:"top20-2": 96249232830474440000 -> 96249232830474440000 (0%) avg:0% +21:"bridge-7-100": 579.9911997249991 -> 579.9911997249991 (0%) avg:0% +22:"bridge-7-300": 579.9911997249991 -> 579.9911997249991 (0%) avg:0% +4:"top20-3": 467011582838851800000 -> 467011582838851800000 (0%) avg:0% +5:"top20-4": 14263706377454.916 -> 14263706377454.916 (0%) avg:0% 6:"top20-5": 111208992328025 -> 111208992328025 (0%) avg:0% 7:"top20-6": 184056193599 -> 184056193599 (0%) avg:0% -21:"bridge-7-100": 579.9911997249991 -> 579.9911997249991 (0%) avg:0% +23:"bridge-7-1000": 578.9911997249991 -> 578.9911997249991 (0%) avg:0% 8:"top20-7": 1.949010266471403e+21 -> 1.949010266471403e+21 (0%) avg:0% 9:"top20-8": 5147698251 -> 5147698251 (0%) avg:0% 10:"top20-9": 2.3146866045567974e+29 -> 2.3146866045567974e+29 (0%) avg:0% -22:"bridge-7-300": 579.9911997249991 -> 579.9911997249991 (0%) avg:0% 11:"top20-10": 2.000939725061475e+25 -> 2.000939725061475e+25 (0%) avg:0% 12:"top20-11": 0 -> 0 (0%) avg:0% 13:"top20-12": 5.998729978399937e+23 -> 5.998729978399937e+23 (0%) avg:0% @@ -34,7 +26,6 @@ 15:"top20-14": 242561332730 -> 242561332730 (0%) avg:0% 16:"top20-15": 20057219983855420 -> 20057219983855420 (0%) avg:0% 17:"top20-16": 1371193183.507006 -> 1371193183.507006 (0%) avg:0% -23:"bridge-7-1000": 578.9911997249991 -> 578.9911997249991 (0%) avg:0% 18:"top20-17": 618784869519468900000 -> 618784869519468900000 (0%) avg:0% 19:"top20-18": 13965130914 -> 13965130914 (0%) avg:0% 20:"top20-19": 1719221840266011.2 -> 1719221840266011.2 (0%) avg:0% diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e887e0e4a6..f8235c75ea 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1589,6 +1589,10 @@ importers: specifier: 3.23.8 version: 3.23.8 + packages/sushi/dist/_cjs: {} + + packages/sushi/dist/_esm: {} + packages/telemetry: devDependencies: '@tsconfig/esm': From 4fec81f20a5adecb73742665bc188c17c16a7440 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Sat, 10 Aug 2024 10:23:44 +0100 Subject: [PATCH 105/125] chore: add missing v2 pool test --- packages/sushi/src/config/sushiswap-v2.ts | 7 + packages/sushi/src/currency/token.ts | 20 + .../sushiswap-v2/sushiswap-v2-pool.test.ts | 653 ++++++++++++++++++ 3 files changed, 680 insertions(+) create mode 100644 packages/sushi/src/pool/sushiswap-v2/sushiswap-v2-pool.test.ts diff --git a/packages/sushi/src/config/sushiswap-v2.ts b/packages/sushi/src/config/sushiswap-v2.ts index d13f47acc2..9e6d7072dc 100644 --- a/packages/sushi/src/config/sushiswap-v2.ts +++ b/packages/sushi/src/config/sushiswap-v2.ts @@ -50,6 +50,7 @@ export const SUSHISWAP_V2_SUPPORTED_CHAIN_IDS = [ // ChainId.RINKEBY, // ChainId.GÖRLI, // ChainId.KOVAN, + ChainId.SEPOLIA, ] as const export const SushiSwapV2ChainIds = SUSHISWAP_V2_SUPPORTED_CHAIN_IDS @@ -159,6 +160,8 @@ export const SUSHISWAP_V2_INIT_CODE_HASH: Record< '0xe18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c6303', [ChainId.ROOTSTOCK]: '0xe18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c6303', + [ChainId.SEPOLIA]: + '0xe18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c6303', } export const SUSHISWAP_V2_FACTORY_ADDRESS: Record< @@ -211,6 +214,8 @@ export const SUSHISWAP_V2_FACTORY_ADDRESS: Record< [ChainId.BLAST]: '0x42Fa929fc636e657AC568C0b5Cf38E203b67aC2b', [ChainId.SKALE_EUROPA]: '0x1aaF6eB4F85F8775400C1B10E6BbbD98b2FF8483', [ChainId.ROOTSTOCK]: '0xB45e53277a7e0F1D35f2a77160e91e25507f1763', + + [ChainId.SEPOLIA]: '0x734583f62Bb6ACe3c9bA9bd5A53143CA2Ce8C55A', } export const SUSHISWAP_V2_ROUTER_ADDRESS: Record< @@ -265,4 +270,6 @@ export const SUSHISWAP_V2_ROUTER_ADDRESS: Record< [ChainId.BLAST]: '0x54CF3d259a06601b5bC45F61A16443ed5404DD64', [ChainId.SKALE_EUROPA]: '0x4cddf8D1473df386b926ec14b23bfbD566CE827a', [ChainId.ROOTSTOCK]: '0x9B3336186a38E1b6c21955d112dbb0343Ee061eE', + + [ChainId.SEPOLIA]: '0xeaBcE3E74EF41FB40024a21Cc2ee2F5dDc615791', } diff --git a/packages/sushi/src/currency/token.ts b/packages/sushi/src/currency/token.ts index 3eda664fdd..2d805ddfd3 100644 --- a/packages/sushi/src/currency/token.ts +++ b/packages/sushi/src/currency/token.ts @@ -16,6 +16,13 @@ export class Token extends Currency { */ public readonly address: Address + /** + * Relevant for fee-on-transfer (FOT) token taxes, + * Not every ERC20 token is FOT token, so this field is optional + */ + public readonly buyFeeBps?: bigint + public readonly sellFeeBps?: bigint + public constructor({ // TODO: // id, @@ -24,12 +31,16 @@ export class Token extends Currency { decimals, symbol, name, + buyFeeBps, + sellFeeBps, }: { chainId: number | string address: string decimals: number | string symbol?: string | undefined name?: string | undefined + buyFeeBps?: bigint + sellFeeBps?: bigint }) { super({ chainId, @@ -44,6 +55,15 @@ export class Token extends Currency { } catch { throw `${address} is not a valid address` } + + if (buyFeeBps) { + invariant(buyFeeBps >= 0n, 'NON-NEGATIVE FOT FEES') + this.buyFeeBps = buyFeeBps + } + if (sellFeeBps) { + invariant(sellFeeBps >= 0n, 'NON-NEGATIVE FOT FEES') + this.sellFeeBps = sellFeeBps + } } /** diff --git a/packages/sushi/src/pool/sushiswap-v2/sushiswap-v2-pool.test.ts b/packages/sushi/src/pool/sushiswap-v2/sushiswap-v2-pool.test.ts new file mode 100644 index 0000000000..dcc6277404 --- /dev/null +++ b/packages/sushi/src/pool/sushiswap-v2/sushiswap-v2-pool.test.ts @@ -0,0 +1,653 @@ +import { describe, expect, it } from 'vitest' +import { ChainId } from '~sushi/chain/constants.js' +import { SUSHISWAP_V2_FACTORY_ADDRESS } from '~sushi/config/sushiswap-v2.js' +import { Amount } from '~sushi/currency/amount.js' +import { Price } from '~sushi/currency/price.js' +import { Token } from '~sushi/currency/token.js' +import { WETH9 } from '~sushi/currency/tokens.js' +import { InsufficientInputAmountError } from '~sushi/dex/errors.js' +import { computeSushiSwapV2PoolAddress } from '~sushi/pool/sushiswap-v2/compute-sushiswap-v2-pool-address.js' +// import { BigNumber } from '@ethersproject/bignumber' +// import { ChainId, CurrencyAmount, Price, Token, V2_FACTORY_ADDRESSES, WETH9 } from '@uniswap/sdk-core' +import { SushiSwapV2Pool } from './sushiswap-v2-pool.js' + +describe('computePairAddress', () => { + it('should correctly compute the pool address', () => { + const tokenA = new Token({ + chainId: 1, + address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + decimals: 18, + symbol: 'USDC', + name: 'USD Coin', + }) + const tokenB = new Token({ + chainId: 1, + address: '0x6B175474E89094C44Da98b954EedeAC495271d0F', + decimals: 18, + symbol: 'DAI', + name: 'DAI Stablecoin', + }) + const result = computeSushiSwapV2PoolAddress({ + factoryAddress: '0x1111111111111111111111111111111111111111', + tokenA, + tokenB, + }) + + expect(result).toEqual('0xbCfFCD50d09095E48CC5ea02d564CAEe61aBc004') + }) + it('should give same result regardless of token order', () => { + const USDC = new Token({ + chainId: 1, + address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + decimals: 18, + symbol: 'USDC', + name: 'USD Coin', + }) + const DAI = new Token({ + chainId: 1, + address: '0x6B175474E89094C44Da98b954EedeAC495271d0F', + decimals: 18, + symbol: 'DAI', + name: 'DAI Stablecoin', + }) + let tokenA = USDC + let tokenB = DAI + const resultA = computeSushiSwapV2PoolAddress({ + factoryAddress: '0x1111111111111111111111111111111111111111', + tokenA, + tokenB, + }) + + tokenA = DAI + tokenB = USDC + const resultB = computeSushiSwapV2PoolAddress({ + factoryAddress: '0x1111111111111111111111111111111111111111', + tokenA, + tokenB, + }) + + expect(resultA).toEqual(resultB) + }) +}) + +describe('Pair', () => { + const USDC = new Token({ + chainId: 1, + address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + decimals: 18, + symbol: 'USDC', + name: 'USD Coin', + }) + const DAI = new Token({ + chainId: 1, + address: '0x6B175474E89094C44Da98b954EedeAC495271d0F', + decimals: 18, + symbol: 'DAI', + name: 'DAI Stablecoin', + }) + + const USDC_SEPOLIA = new Token({ + chainId: 11155111, + address: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', + decimals: 18, + symbol: 'USDC', + name: 'USD Coin', + }) + const DAI_SEPOLIA = new Token({ + chainId: 11155111, + address: '0x6B175474E89094C44Da98b954EedeAC495271d0F', + decimals: 18, + symbol: 'DAI', + name: 'DAI Stablecoin', + }) + + describe('constructor', () => { + it('cannot be used for tokens on different chains', () => { + expect( + () => + new SushiSwapV2Pool( + Amount.fromRawAmount(USDC, '100'), + Amount.fromRawAmount(WETH9[ChainId.SEPOLIA], '100'), + ), + ).toThrow('CHAIN_IDS') + }) + }) + + describe('#getAddress', () => { + it('returns the correct address', () => { + expect(SushiSwapV2Pool.getAddress(USDC, DAI)).toEqual( + '0xAaF5110db6e744ff70fB339DE037B990A20bdace', + ) + }) + + it.skip('returns the default address for a testnet not in the map', () => { + expect(() => + SushiSwapV2Pool.getAddress(USDC_SEPOLIA, DAI_SEPOLIA), + ).toEqual( + computeSushiSwapV2PoolAddress({ + factoryAddress: SUSHISWAP_V2_FACTORY_ADDRESS[ChainId.SEPOLIA], + tokenA: USDC_SEPOLIA, + tokenB: DAI_SEPOLIA, + }), + ) + }) + }) + + describe('#token0', () => { + it('always is the token that sorts before', () => { + expect( + new SushiSwapV2Pool( + Amount.fromRawAmount(USDC, '100'), + Amount.fromRawAmount(DAI, '100'), + ).token0, + ).toEqual(DAI) + expect( + new SushiSwapV2Pool( + Amount.fromRawAmount(DAI, '100'), + Amount.fromRawAmount(USDC, '100'), + ).token0, + ).toEqual(DAI) + }) + }) + describe('#token1', () => { + it('always is the token that sorts after', () => { + expect( + new SushiSwapV2Pool( + Amount.fromRawAmount(USDC, '100'), + Amount.fromRawAmount(DAI, '100'), + ).token1, + ).toEqual(USDC) + expect( + new SushiSwapV2Pool( + Amount.fromRawAmount(DAI, '100'), + Amount.fromRawAmount(USDC, '100'), + ).token1, + ).toEqual(USDC) + }) + }) + describe('#reserve0', () => { + it('always comes from the token that sorts before', () => { + expect( + new SushiSwapV2Pool( + Amount.fromRawAmount(USDC, '100'), + Amount.fromRawAmount(DAI, '101'), + ).reserve0, + ).toEqual(Amount.fromRawAmount(DAI, '101')) + expect( + new SushiSwapV2Pool( + Amount.fromRawAmount(DAI, '101'), + Amount.fromRawAmount(USDC, '100'), + ).reserve0, + ).toEqual(Amount.fromRawAmount(DAI, '101')) + }) + }) + describe('#reserve1', () => { + it('always comes from the token that sorts after', () => { + expect( + new SushiSwapV2Pool( + Amount.fromRawAmount(USDC, '100'), + Amount.fromRawAmount(DAI, '101'), + ).reserve1, + ).toEqual(Amount.fromRawAmount(USDC, '100')) + expect( + new SushiSwapV2Pool( + Amount.fromRawAmount(DAI, '101'), + Amount.fromRawAmount(USDC, '100'), + ).reserve1, + ).toEqual(Amount.fromRawAmount(USDC, '100')) + }) + }) + + describe('#token0Price', () => { + it('returns price of token0 in terms of token1', () => { + expect( + new SushiSwapV2Pool( + Amount.fromRawAmount(USDC, '101'), + Amount.fromRawAmount(DAI, '100'), + ).token0Price, + ).toEqual(new Price(DAI, USDC, '100', '101')) + expect( + new SushiSwapV2Pool( + Amount.fromRawAmount(DAI, '100'), + Amount.fromRawAmount(USDC, '101'), + ).token0Price, + ).toEqual(new Price(DAI, USDC, '100', '101')) + }) + }) + + describe('#token1Price', () => { + it('returns price of token1 in terms of token0', () => { + expect( + new SushiSwapV2Pool( + Amount.fromRawAmount(USDC, '101'), + Amount.fromRawAmount(DAI, '100'), + ).token1Price, + ).toEqual(new Price(USDC, DAI, '101', '100')) + expect( + new SushiSwapV2Pool( + Amount.fromRawAmount(DAI, '100'), + Amount.fromRawAmount(USDC, '101'), + ).token1Price, + ).toEqual(new Price(USDC, DAI, '101', '100')) + }) + }) + + describe('#priceOf', () => { + const pair = new SushiSwapV2Pool( + Amount.fromRawAmount(USDC, '101'), + Amount.fromRawAmount(DAI, '100'), + ) + it('returns price of token in terms of other token', () => { + expect(pair.priceOf(DAI)).toEqual(pair.token0Price) + expect(pair.priceOf(USDC)).toEqual(pair.token1Price) + }) + + it('throws if invalid token', () => { + expect(() => pair.priceOf(WETH9[1])).toThrow('TOKEN') + }) + }) + + describe('#reserveOf', () => { + it('returns reserves of the given token', () => { + expect( + new SushiSwapV2Pool( + Amount.fromRawAmount(USDC, '100'), + Amount.fromRawAmount(DAI, '101'), + ).reserveOf(USDC), + ).toEqual(Amount.fromRawAmount(USDC, '100')) + expect( + new SushiSwapV2Pool( + Amount.fromRawAmount(DAI, '101'), + Amount.fromRawAmount(USDC, '100'), + ).reserveOf(USDC), + ).toEqual(Amount.fromRawAmount(USDC, '100')) + }) + + it('throws if not in the pair', () => { + expect(() => + new SushiSwapV2Pool( + Amount.fromRawAmount(DAI, '101'), + Amount.fromRawAmount(USDC, '100'), + ).reserveOf(WETH9[1]), + ).toThrow('TOKEN') + }) + }) + + describe('#chainId', () => { + it('returns the token0 chainId', () => { + expect( + new SushiSwapV2Pool( + Amount.fromRawAmount(USDC, '100'), + Amount.fromRawAmount(DAI, '100'), + ).chainId, + ).toEqual(1) + expect( + new SushiSwapV2Pool( + Amount.fromRawAmount(DAI, '100'), + Amount.fromRawAmount(USDC, '100'), + ).chainId, + ).toEqual(1) + }) + }) + describe('#involvesToken', () => { + it('returns true for either token', () => { + expect( + new SushiSwapV2Pool( + Amount.fromRawAmount(USDC, '100'), + Amount.fromRawAmount(DAI, '100'), + ).involvesToken(USDC), + ).toEqual(true) + expect( + new SushiSwapV2Pool( + Amount.fromRawAmount(USDC, '100'), + Amount.fromRawAmount(DAI, '100'), + ).involvesToken(DAI), + ).toEqual(true) + expect( + new SushiSwapV2Pool( + Amount.fromRawAmount(USDC, '100'), + Amount.fromRawAmount(DAI, '100'), + ).involvesToken(WETH9[1]), + ).toEqual(false) + }) + }) + describe('getInputAmount and getOutputAmount', () => { + const BLASTBuyFeeBps = 400n + const BLASTSellFeeBps = 10000n + const BLAST = new Token({ + chainId: ChainId.ETHEREUM, + address: '0x3ed643e9032230f01c6c36060e305ab53ad3b482', + decimals: 18, + symbol: 'BLAST', + name: 'BLASTERS', + buyFeeBps: BLASTBuyFeeBps, + sellFeeBps: BLASTSellFeeBps, + }) + const BLAST_WIHTOUT_TAX = new Token({ + chainId: ChainId.ETHEREUM, + address: '0x3ed643e9032230f01c6c36060e305ab53ad3b482', + decimals: 18, + symbol: 'BLAST', + name: 'BLASTERS', + }) + const BLASTERSBuyFeeBps = 300n + const BLASTERSSellFeeBps = 350n + const BLASTERS = new Token({ + chainId: ChainId.ETHEREUM, + address: '0xab98093C7232E98A47D7270CE0c1c2106f61C73b', + decimals: 9, + symbol: 'BLAST', + name: 'BLASTERS', + buyFeeBps: BLASTERSBuyFeeBps, + sellFeeBps: BLASTERSSellFeeBps, + }) + const BLASTERS_WITHOUT_TAX = new Token({ + chainId: ChainId.ETHEREUM, + address: '0xab98093C7232E98A47D7270CE0c1c2106f61C73b', + decimals: 9, + symbol: 'BLAST', + name: 'BLASTERS', + }) + + // let calculateFotFees = false + + // describe('when calculating FOT fees', () => { + // beforeEach(() => { + // calculateFotFees = true + // }) + + // describe('getOutputAmount', () => { + // it('getOutputAmount for input token BLASTERS and output token BLAST', () => { + // const reserveBlasterAmount = Amount.fromRawAmount( + // BLASTERS, + // '10000', + // ) + // const reserveBlastAmount = Amount.fromRawAmount( + // BLAST, + // '10000', + // ) + + // const pair = new SushiSwapV2Pool(reserveBlasterAmount, reserveBlastAmount) + + // const inputBlastersAmount = Amount.fromRawAmount( + // BLASTERS_WITHOUT_TAX, + // '100', + // ) + // const [outputBlastAmount] = pair.getOutputAmount( + // inputBlastersAmount, + // calculateFotFees, + // ) + + // // Theoretical amount out: + // // (10000 * 997 * 100 * (1 - 3.5%) / (10000 * 1000 + 997 * 100 * (1 - 3.5%))) * (1 - 4%) + // // = 91.48 + // // + // // However in practice, we have round down of precisions in multiple steps + // // hence the amount out will be slightly less than 91.48: + // // + // // inputAmount = 100 + // // percentAfterSellFeesInDecimal = fraction(9650, 10000) + // // inputAmountAfterTax = 100 * fraction(9650, 10000) = 96.5 = 96 (rounded down) + // // inputAmountWithFeeAndAfterTax = 96 * 997 = 95712 + // // numerator = 95712 * 10000 = 957120000 + // // denominator = 10000 * 1000 + 95712 = 10095712 + // // outputAmount = 957120000 / 10095712 = 94.8046061536 = 94 (rounded down) + // // buyFeePercentInDecimal = fraction(400, 10000) + // // percentAfterBuyFeesInDecimal = fraction(9600, 10000) + // // outputAmountAfterTax = 94 * fraction(9600, 10000) + // // = 94 * 0.96 + // // = 90.24 + // // = 90 (rounded down) + // const expectedOutputBlastAmount = '0.00000000000000009' + // expect(outputBlastAmount.toExact()).toEqual(expectedOutputBlastAmount) + // }) + + // it('getInputAmount for input token BLASTERS and output token BLAST', () => { + // const reserveBlasterAmount = Amount.fromRawAmount( + // BLASTERS, + // '10000', + // ) + // const reserveBlastAmount = Amount.fromRawAmount( + // BLAST, + // '10000', + // ) + + // const pair = new SushiSwapV2Pool(reserveBlasterAmount, reserveBlastAmount) + + // const outputBlastAmount = Amount.fromRawAmount( + // BLAST_WIHTOUT_TAX, + // '91', + // ) + // const [inputBlasterAmount] = pair.getInputAmount( + // outputBlastAmount, + // calculateFotFees, + // ) + + // // Theoretical amount in: + // // 10000 * 100 * (1 - 4%) * 1000 / ((10000 - 100 * (1 - 4%)) * 997) / (1 - 3.5%) + // // = 100.7483934892 + // // + // // However in practice, we have round up of precisions in multiple steps + // // hence the amount out will be slightly more than 100.7483934892: + // // + // // buyFeePercentInDecimal = fraction(400, 10000) + // // percentAfterBuyFeesInDecimal = 1 - fraction(400, 10000) = fraction(9600, 10000) + // // outputAmountBeforeTax = 91 / fraction(960000, 10000) + 1 + // // = 91 / 0.96 + 1 + // // = 94.7916666667 + 1 + // // = 94 (rounded down) + 1 + // // = 95 (rounded up) + // // numerator = 10000 * 95 * 1000 = 950000000 + // // denominator = (10000 - 95) * 997 = 9875285 + // // inputAmount = 950000000 / 9875285 + 1 + // // = 96.1997552476 + 1 + // // = 96 (rounded down) + 1 + // // = 97 (rounded up) + // // sellFeePercentInDecimal = fraction(350, 10000) + // // percentAfterSellFeesInDecimal = 1 - fraction(350, 10000) = fraction(9650, 10000) + // // inputAmountBeforeTax = (97 / fraction(9650, 10000)) + 1 + // // = (97 / 0.965) + 1 + // // = 100.518134715 + 1 + // // = 100 (rounded down) + 1 + // // = 101 + // const expectedInputBlasterAmount = '0.000000101' + // expect(inputBlasterAmount.toExact()).toEqual( + // expectedInputBlasterAmount, + // ) + // }) + // }) + // }) + + describe('when NOT calculating FOT fees', () => { + describe('getOutputAmount', () => { + it('getOutputAmount for input token BLASTERS and output token BLAST', () => { + const reserveBlasterAmount = Amount.fromRawAmount(BLASTERS, '10000') + const reserveBlastAmount = Amount.fromRawAmount(BLAST, '10000') + + const pair = new SushiSwapV2Pool( + reserveBlasterAmount, + reserveBlastAmount, + ) + + const inputBlastersAmount = Amount.fromRawAmount( + BLASTERS_WITHOUT_TAX, + '100', + ) + const [outputBlastAmount] = pair.getOutputAmount(inputBlastersAmount) + + const expectedOutputBlastAmount = '0.000000000000000098' + expect(outputBlastAmount.toExact()).toEqual(expectedOutputBlastAmount) + }) + + it('getInputAmount for input token BLASTERS and output token BLAST', () => { + const reserveBlasterAmount = Amount.fromRawAmount(BLASTERS, '10000') + const reserveBlastAmount = Amount.fromRawAmount(BLAST, '10000') + + const pair = new SushiSwapV2Pool( + reserveBlasterAmount, + reserveBlastAmount, + ) + + const outputBlastAmount = Amount.fromRawAmount( + BLAST_WIHTOUT_TAX, + '91', + ) + const [inputBlasterAmount] = pair.getInputAmount(outputBlastAmount) + + const expectedInputBlasterAmount = '0.000000093' + expect(inputBlasterAmount.toExact()).toEqual( + expectedInputBlasterAmount, + ) + }) + }) + }) + }) + describe('miscellaneous', () => { + it('getLiquidityMinted:0', async () => { + const tokenA = new Token({ + chainId: ChainId.SEPOLIA, + address: '0x0000000000000000000000000000000000000001', + decimals: 18, + }) + const tokenB = new Token({ + chainId: ChainId.SEPOLIA, + address: '0x0000000000000000000000000000000000000002', + decimals: 18, + }) + const pair = new SushiSwapV2Pool( + Amount.fromRawAmount(tokenA, '0'), + Amount.fromRawAmount(tokenB, '0'), + ) + + expect(() => { + pair.getLiquidityMinted( + Amount.fromRawAmount(pair.liquidityToken, '0'), + Amount.fromRawAmount(tokenA, '1000'), + Amount.fromRawAmount(tokenB, '1000'), + ) + }).toThrow(InsufficientInputAmountError) + + expect(() => { + pair.getLiquidityMinted( + Amount.fromRawAmount(pair.liquidityToken, '0'), + Amount.fromRawAmount(tokenA, '1000000'), + Amount.fromRawAmount(tokenB, '1'), + ) + }).toThrow(InsufficientInputAmountError) + + const liquidity = pair.getLiquidityMinted( + Amount.fromRawAmount(pair.liquidityToken, '0'), + Amount.fromRawAmount(tokenA, '1001'), + Amount.fromRawAmount(tokenB, '1001'), + ) + + expect(liquidity.quotient.toString()).toEqual('1') + }) + + it('getLiquidityMinted:!0', async () => { + const tokenA = new Token({ + chainId: ChainId.SEPOLIA, + address: '0x0000000000000000000000000000000000000001', + decimals: 18, + }) + const tokenB = new Token({ + chainId: ChainId.SEPOLIA, + address: '0x0000000000000000000000000000000000000002', + decimals: 18, + }) + const pair = new SushiSwapV2Pool( + Amount.fromRawAmount(tokenA, '10000'), + Amount.fromRawAmount(tokenB, '10000'), + ) + + expect( + pair + .getLiquidityMinted( + Amount.fromRawAmount(pair.liquidityToken, '10000'), + Amount.fromRawAmount(tokenA, '2000'), + Amount.fromRawAmount(tokenB, '2000'), + ) + .quotient.toString(), + ).toEqual('2000') + }) + + it('getLiquidityValue:!feeOn', async () => { + const tokenA = new Token({ + chainId: ChainId.SEPOLIA, + address: '0x0000000000000000000000000000000000000001', + decimals: 18, + }) + const tokenB = new Token({ + chainId: ChainId.SEPOLIA, + address: '0x0000000000000000000000000000000000000002', + decimals: 18, + }) + const pair = new SushiSwapV2Pool( + Amount.fromRawAmount(tokenA, '1000'), + Amount.fromRawAmount(tokenB, '1000'), + ) + + { + const liquidityValue = pair.getLiquidityValue( + tokenA, + Amount.fromRawAmount(pair.liquidityToken, '1000'), + Amount.fromRawAmount(pair.liquidityToken, '1000'), + false, + ) + expect(liquidityValue.currency.equals(tokenA)).toBe(true) + expect(liquidityValue.quotient.toString()).toBe('1000') + } + + // 500 + { + const liquidityValue = pair.getLiquidityValue( + tokenA, + Amount.fromRawAmount(pair.liquidityToken, '1000'), + Amount.fromRawAmount(pair.liquidityToken, '500'), + false, + ) + expect(liquidityValue.currency.equals(tokenA)).toBe(true) + expect(liquidityValue.quotient.toString()).toBe('500') + } + + // tokenB + { + const liquidityValue = pair.getLiquidityValue( + tokenB, + Amount.fromRawAmount(pair.liquidityToken, '1000'), + Amount.fromRawAmount(pair.liquidityToken, '1000'), + false, + ) + expect(liquidityValue.currency.equals(tokenB)).toBe(true) + expect(liquidityValue.quotient.toString()).toBe('1000') + } + }) + + it('getLiquidityValue:feeOn', async () => { + const tokenA = new Token({ + chainId: ChainId.SEPOLIA, + address: '0x0000000000000000000000000000000000000001', + decimals: 18, + }) + const tokenB = new Token({ + chainId: ChainId.SEPOLIA, + address: '0x0000000000000000000000000000000000000002', + decimals: 18, + }) + const pair = new SushiSwapV2Pool( + Amount.fromRawAmount(tokenA, '1000'), + Amount.fromRawAmount(tokenB, '1000'), + ) + + const liquidityValue = pair.getLiquidityValue( + tokenA, + Amount.fromRawAmount(pair.liquidityToken, '500'), + Amount.fromRawAmount(pair.liquidityToken, '500'), + true, + '250000', // 500 ** 2 + ) + expect(liquidityValue.currency.equals(tokenA)).toBe(true) + expect(liquidityValue.quotient.toString()).toBe('917') // ceiling(1000 - (500 * (1 / 6))) + }) + }) +}) From 29514fa66c0d2770b10b304bb701c64de0698d08 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Sat, 10 Aug 2024 10:31:07 +0100 Subject: [PATCH 106/125] fix: compilation --- packages/sushi/src/config/subgraph/subgraphs/sushiswap-v2.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/sushi/src/config/subgraph/subgraphs/sushiswap-v2.ts b/packages/sushi/src/config/subgraph/subgraphs/sushiswap-v2.ts index 6cb50a475f..9f312335a2 100644 --- a/packages/sushi/src/config/subgraph/subgraphs/sushiswap-v2.ts +++ b/packages/sushi/src/config/subgraph/subgraphs/sushiswap-v2.ts @@ -44,4 +44,5 @@ export const SUSHISWAP_V2_SUBGRAPH_URL: Record = { [ChainId.BLAST]: `${SUSHI_DEDICATED_GOLDSKY_HOST}/sushiswap/v2-blast/gn`, [ChainId.SKALE_EUROPA]: `${SKALE_HOST}/sushi/v2-skale-europa`, [ChainId.ROOTSTOCK]: `${SUSHI_DEDICATED_GOLDSKY_HOST}/sushiswap/v2-rootstock/gn`, + [ChainId.SEPOLIA]: '', } From 2cd6dbc14b8befd8a1370afb3cdcbded9c533703 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Sat, 10 Aug 2024 11:20:16 +0100 Subject: [PATCH 107/125] fix: remove build from from changeset workflow --- .github/workflows/changesets.yaml | 83 +++++++++++++++++++++++++++++++ .github/workflows/release.yml | 58 --------------------- .github/workflows/verify.yml | 23 ++++++++- 3 files changed, 105 insertions(+), 59 deletions(-) create mode 100644 .github/workflows/changesets.yaml delete mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/changesets.yaml b/.github/workflows/changesets.yaml new file mode 100644 index 0000000000..22e22c47d4 --- /dev/null +++ b/.github/workflows/changesets.yaml @@ -0,0 +1,83 @@ +name: Changesets +on: + push: + branches: [master] + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + verify: + name: Verify + uses: ./.github/workflows/verify.yml + secrets: inherit + + changesets: + name: Create version pull request + runs-on: ubuntu-latest + timeout-minutes: 5 + + steps: + - name: Clone repository + uses: actions/checkout@v4 + with: + # This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits + fetch-depth: 0 + submodules: 'recursive' + + - name: Install dependencies + uses: ./.github/actions/install + + - name: Create Version Pull Request + uses: changesets/action@v1 + with: + commit: 'chore: version package' + title: 'chore: version package' + version: pnpm changeset:version + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + release: + name: Release + needs: verify + runs-on: ubuntu-latest + timeout-minutes: 5 + permissions: + contents: write + id-token: write + pull-requests: write + + steps: + - name: Clone repository + uses: actions/checkout@v4 + with: + submodules: 'recursive' + + - name: Install dependencies + uses: ./.github/actions/install + + - name: Publish to NPM + uses: changesets/action@v1 + with: + createGithubReleases: ${{ github.ref == 'refs/heads/main' }} + publish: pnpm changeset:publish + version: pnpm changeset:version + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: Publish Prerelease + if: steps.changesets.outputs.published != 'true' + continue-on-error: true + env: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + npm config set "//registry.npmjs.org/:_authToken" "$NPM_TOKEN" + git reset --hard origin/main + pnpm clean + pnpm changeset version --no-git-tag --snapshot canary + pnpm changeset:prepublish + pnpm changeset publish --no-git-tag --snapshot canary --tag canary \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index a1fd8edfb5..0000000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,58 +0,0 @@ -name: Changesets - -on: - push: - branches: - - master - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -env: - CI: true - TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} - TURBO_TEAM: ${{ secrets.TURBO_TEAM }} - DATABASE_URL: ${{ secrets.DATABASE_URL }} - -jobs: - release: - name: Release - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v3 - with: - fetch-depth: 0 - submodules: true - - - uses: pnpm/action-setup@v4 - with: - version: 9.4.0 - - - name: Setup Node.js - uses: actions/setup-node@v3 - with: - node-version: 20 - cache: 'pnpm' - - - name: Install dependencies - run: pnpm install - - - name: Build packages - run: pnpm exec turbo run build --filter=./packages/* - - - name: Build config - run: pnpm exec turbo run build --filter=./config/* - - - name: Create Release Pull Request or Publish to npm - id: changesets - uses: changesets/action@v1 - with: - title: "chore: version packages" - commit: "chore: version packages" - publish: pnpm changeset:release - version: pnpm changeset:version - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - NPM_TOKEN: ${{ secrets.NPM_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index 230b1edd66..d9abb69bbe 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -55,7 +55,28 @@ jobs: commit_message: 'chore: lint' commit_user_name: 'github-actions[bot]' commit_user_email: 'github-actions[bot]@users.noreply.github.com' - + + build: + name: Build + needs: lint + runs-on: ubuntu-latest + timeout-minutes: 5 + + steps: + - name: Clone repository + uses: actions/checkout@v4 + with: + submodules: 'recursive' + + - name: Install dependencies + uses: ./.github/actions/install + + - name: Build packages + run: pnpm exec turbo run build --filter=./packages/* + + - name: Build config + run: pnpm exec turbo run build --filter=./config/* + # build: # name: Build # needs: [lint, format] From 53d50c75c68da3ac3ec6ef2916a4a330391c5f9a Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Sat, 10 Aug 2024 11:22:56 +0100 Subject: [PATCH 108/125] workflow: on workflow call/dispatch --- .github/workflows/verify.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index d9abb69bbe..3a8ea3253e 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -3,8 +3,10 @@ name: Sushi - verify # workflow_call: # workflow_dispatch: on: - pull_request: - types: [opened, synchronize] + workflow_call: + workflow_dispatch: + # pull_request: + # types: [opened, synchronize] env: TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} TURBO_TEAM: ${{ secrets.TURBO_TEAM }} From 7282cef13eacdbf1e562e45590bdba180c723998 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Sat, 10 Aug 2024 11:29:05 +0100 Subject: [PATCH 109/125] workflow: changesets --- .github/workflows/pull-request.yml | 13 +++++++++++++ .github/workflows/verify.yml | 2 ++ 2 files changed, 15 insertions(+) create mode 100644 .github/workflows/pull-request.yml diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml new file mode 100644 index 0000000000..38dc329c2c --- /dev/null +++ b/.github/workflows/pull-request.yml @@ -0,0 +1,13 @@ +name: Pull request +on: + pull_request: + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + verify: + name: Verify + uses: ./.github/workflows/verify.yml + secrets: inherit diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index 3a8ea3253e..9a0279be8a 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -22,6 +22,7 @@ jobs: - name: Clone repository uses: actions/checkout@v4 with: + submodules: 'recursive' token: ${{ secrets.PAT }} ref: ${{ github.head_ref }} - name: Install dependencies @@ -44,6 +45,7 @@ jobs: - name: Clone repository uses: actions/checkout@v4 with: + submodules: 'recursive' token: ${{ secrets.PAT }} ref: ${{ github.head_ref }} - name: Install dependencies From 547c8b8dc6d23874473dc37a21958a961acf0a3f Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Sat, 10 Aug 2024 11:36:07 +0100 Subject: [PATCH 110/125] stale.yml --- .github/stale.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .github/stale.yml diff --git a/.github/stale.yml b/.github/stale.yml new file mode 100644 index 0000000000..c678951ee3 --- /dev/null +++ b/.github/stale.yml @@ -0,0 +1,17 @@ +# Number of days of inactivity before an issue becomes stale +daysUntilStale: 180 +# Number of days of inactivity before a stale issue is closed +daysUntilClose: 7 +# Issues with these labels will never be considered stale +exemptLabels: + - bug + - not stale +# Label to use when marking an issue as stale +staleLabel: stale +# Comment to post when marking an issue as stale. Set to `false` to disable +markComment: > + This issue has been automatically marked as stale because it has not had + recent activity. It will be closed if no further activity occurs. Thank you + for your contributions. +# Comment to post when closing a stale issue. Set to `false` to disable +closeComment: false \ No newline at end of file From 1a6ed994fb1ecc8369e67c852b01e9e8b2448a56 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Sat, 10 Aug 2024 11:37:05 +0100 Subject: [PATCH 111/125] security --- .github/SECURITY.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .github/SECURITY.md diff --git a/.github/SECURITY.md b/.github/SECURITY.md new file mode 100644 index 0000000000..afda148db9 --- /dev/null +++ b/.github/SECURITY.md @@ -0,0 +1,9 @@ +# Security Policy + +## Reporting a Vulnerability + +If you identify a vulnerability, please email security@sushi.com with: + +- Description +- Suggested impact (Critical, High, Medium, Low) +- Minimal reproducible example \ No newline at end of file From 4ecd02e9a14c9dfea977138966f5a060b34cdfb8 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Sat, 10 Aug 2024 11:42:18 +0100 Subject: [PATCH 112/125] fix: remove concurrency from verify --- .github/workflows/verify.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index 9a0279be8a..d19313c81c 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -10,9 +10,7 @@ on: env: TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }} TURBO_TEAM: ${{ secrets.TURBO_TEAM }} -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true + jobs: format: name: Format From 63d4ebe645f546a47401e34f7d2da2d95da6edcb Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Sat, 10 Aug 2024 11:48:51 +0100 Subject: [PATCH 113/125] chore: add sushi changeset --- .changeset/config.json | 1 - .changeset/loud-donkeys-camp.md | 5 +++++ pnpm-lock.yaml | 5 ----- 3 files changed, 5 insertions(+), 6 deletions(-) create mode 100644 .changeset/loud-donkeys-camp.md diff --git a/.changeset/config.json b/.changeset/config.json index fa6b26cd69..1badab8162 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -20,7 +20,6 @@ "@sushiswap/notifications", "@sushiswap/ui", "@sushiswap/pool-job", - "@sushiswap/aptos", "@sushiswap/tron", "web" ] diff --git a/.changeset/loud-donkeys-camp.md b/.changeset/loud-donkeys-camp.md new file mode 100644 index 0000000000..ca2cab5ac6 --- /dev/null +++ b/.changeset/loud-donkeys-camp.md @@ -0,0 +1,5 @@ +--- +"sushi": minor +--- + +configuration diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f8235c75ea..5f2fae14b6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1589,10 +1589,6 @@ importers: specifier: 3.23.8 version: 3.23.8 - packages/sushi/dist/_cjs: {} - - packages/sushi/dist/_esm: {} - packages/telemetry: devDependencies: '@tsconfig/esm': @@ -22165,7 +22161,6 @@ packages: web3-provider-engine@14.2.1: resolution: {integrity: sha512-iSv31h2qXkr9vrL6UZDm4leZMc32SjWJFGOp/D92JXfcEboCqraZyuExDkpxKw8ziTufXieNM7LSXNHzszYdJw==} - deprecated: 'This package has been deprecated, see the README for details: https://github.com/MetaMask/web3-provider-engine' web3-providers-http@1.10.3: resolution: {integrity: sha512-6dAgsHR3MxJ0Qyu3QLFlQEelTapVfWNTu5F45FYh8t7Y03T1/o+YAkVxsbY5AdmD+y5bXG/XPJ4q8tjL6MgZHw==} From 3f9079b3aee66c022ba316e80985dffa257d31b2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 10 Aug 2024 11:00:32 +0000 Subject: [PATCH 114/125] Version Packages --- .changeset/loud-donkeys-camp.md | 5 ----- apis/extractor/CHANGELOG.md | 9 +++++++++ apis/extractor/package.json | 2 +- apis/router/CHANGELOG.md | 9 +++++++++ apis/router/package.json | 2 +- config/wagmi/CHANGELOG.md | 7 +++++++ config/wagmi/package.json | 2 +- packages/bonds-sdk/CHANGELOG.md | 7 +++++++ packages/bonds-sdk/package.json | 2 +- packages/extractor/CHANGELOG.md | 7 +++++++ packages/extractor/package.json | 2 +- packages/graph-client/CHANGELOG.md | 10 ++++++++++ packages/graph-client/package.json | 2 +- packages/hooks/CHANGELOG.md | 7 +++++++ packages/hooks/package.json | 2 +- packages/steer-sdk/CHANGELOG.md | 9 +++++++++ packages/steer-sdk/package.json | 2 +- packages/sushi/CHANGELOG.md | 6 ++++++ packages/sushi/package.json | 2 +- 19 files changed, 80 insertions(+), 14 deletions(-) delete mode 100644 .changeset/loud-donkeys-camp.md create mode 100644 apis/extractor/CHANGELOG.md create mode 100644 apis/router/CHANGELOG.md create mode 100644 packages/graph-client/CHANGELOG.md create mode 100644 packages/steer-sdk/CHANGELOG.md diff --git a/.changeset/loud-donkeys-camp.md b/.changeset/loud-donkeys-camp.md deleted file mode 100644 index ca2cab5ac6..0000000000 --- a/.changeset/loud-donkeys-camp.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"sushi": minor ---- - -configuration diff --git a/apis/extractor/CHANGELOG.md b/apis/extractor/CHANGELOG.md new file mode 100644 index 0000000000..416d5953c6 --- /dev/null +++ b/apis/extractor/CHANGELOG.md @@ -0,0 +1,9 @@ +# @sushiswap/extractor-api + +## 0.0.1 + +### Patch Changes + +- Updated dependencies [[`63d4ebe64`](https://github.com/sushiswap/sushiswap/commit/63d4ebe645f546a47401e34f7d2da2d95da6edcb)]: + - sushi@3.1.0 + - @sushiswap/extractor@1.0.2 diff --git a/apis/extractor/package.json b/apis/extractor/package.json index ca142c4dc7..ba756ccaec 100644 --- a/apis/extractor/package.json +++ b/apis/extractor/package.json @@ -1,6 +1,6 @@ { "name": "@sushiswap/extractor-api", - "version": "0.0.0", + "version": "0.0.1", "private": true, "description": "Sushi Extractor API", "keywords": [ diff --git a/apis/router/CHANGELOG.md b/apis/router/CHANGELOG.md new file mode 100644 index 0000000000..4ed91edddd --- /dev/null +++ b/apis/router/CHANGELOG.md @@ -0,0 +1,9 @@ +# @sushiswap/router-api + +## 0.0.1 + +### Patch Changes + +- Updated dependencies [[`63d4ebe64`](https://github.com/sushiswap/sushiswap/commit/63d4ebe645f546a47401e34f7d2da2d95da6edcb)]: + - sushi@3.1.0 + - @sushiswap/extractor@1.0.2 diff --git a/apis/router/package.json b/apis/router/package.json index d3695b934a..1f5295644a 100644 --- a/apis/router/package.json +++ b/apis/router/package.json @@ -1,6 +1,6 @@ { "name": "@sushiswap/router-api", - "version": "0.0.0", + "version": "0.0.1", "private": true, "description": "Sushi Router API", "keywords": [ diff --git a/config/wagmi/CHANGELOG.md b/config/wagmi/CHANGELOG.md index ef3519a582..7972b1628b 100644 --- a/config/wagmi/CHANGELOG.md +++ b/config/wagmi/CHANGELOG.md @@ -1,5 +1,12 @@ # @sushiswap/wagmi-config +## 2.0.0 + +### Patch Changes + +- Updated dependencies [[`63d4ebe64`](https://github.com/sushiswap/sushiswap/commit/63d4ebe645f546a47401e34f7d2da2d95da6edcb)]: + - sushi@3.1.0 + ## 1.0.0 ### Patch Changes diff --git a/config/wagmi/package.json b/config/wagmi/package.json index a4271b25ea..672321c722 100644 --- a/config/wagmi/package.json +++ b/config/wagmi/package.json @@ -1,6 +1,6 @@ { "name": "@sushiswap/wagmi-config", - "version": "1.0.0", + "version": "2.0.0", "description": "Sushi Wagmi Config", "keywords": [ "sushi", diff --git a/packages/bonds-sdk/CHANGELOG.md b/packages/bonds-sdk/CHANGELOG.md index eeb78caaf8..c9c725b39c 100644 --- a/packages/bonds-sdk/CHANGELOG.md +++ b/packages/bonds-sdk/CHANGELOG.md @@ -1,5 +1,12 @@ # @sushiswap/v3-sdk +## 0.0.1 + +### Patch Changes + +- Updated dependencies [[`63d4ebe64`](https://github.com/sushiswap/sushiswap/commit/63d4ebe645f546a47401e34f7d2da2d95da6edcb)]: + - sushi@3.1.0 + ## 1.0.12 ### Patch Changes diff --git a/packages/bonds-sdk/package.json b/packages/bonds-sdk/package.json index 65782852e8..669547f013 100644 --- a/packages/bonds-sdk/package.json +++ b/packages/bonds-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@sushiswap/bonds-sdk", - "version": "0.0.0", + "version": "0.0.1", "private": true, "description": "Sushi Bonds SDK", "keywords": [ diff --git a/packages/extractor/CHANGELOG.md b/packages/extractor/CHANGELOG.md index 07b6c9da55..809f1211d9 100644 --- a/packages/extractor/CHANGELOG.md +++ b/packages/extractor/CHANGELOG.md @@ -1,5 +1,12 @@ # @sushiswap/extractor +## 1.0.2 + +### Patch Changes + +- Updated dependencies [[`63d4ebe64`](https://github.com/sushiswap/sushiswap/commit/63d4ebe645f546a47401e34f7d2da2d95da6edcb)]: + - sushi@3.1.0 + ## 1.0.1 ### Patch Changes diff --git a/packages/extractor/package.json b/packages/extractor/package.json index 515aa12f0c..62c85f1f64 100644 --- a/packages/extractor/package.json +++ b/packages/extractor/package.json @@ -1,6 +1,6 @@ { "name": "@sushiswap/extractor", - "version": "1.0.1", + "version": "1.0.2", "description": "Sushi Extractor", "keywords": [ "sushi", diff --git a/packages/graph-client/CHANGELOG.md b/packages/graph-client/CHANGELOG.md new file mode 100644 index 0000000000..9c85b18f4d --- /dev/null +++ b/packages/graph-client/CHANGELOG.md @@ -0,0 +1,10 @@ +# @sushiswap/graph-client + +## 0.0.1 + +### Patch Changes + +- Updated dependencies [[`63d4ebe64`](https://github.com/sushiswap/sushiswap/commit/63d4ebe645f546a47401e34f7d2da2d95da6edcb)]: + - sushi@3.1.0 + - @sushiswap/bonds-sdk@0.0.1 + - @sushiswap/steer-sdk@0.0.1 diff --git a/packages/graph-client/package.json b/packages/graph-client/package.json index fb8b952edd..32330c3a84 100644 --- a/packages/graph-client/package.json +++ b/packages/graph-client/package.json @@ -1,6 +1,6 @@ { "name": "@sushiswap/graph-client", - "version": "0.0.0", + "version": "0.0.1", "description": "Graph Client", "keywords": [ "sushi", diff --git a/packages/hooks/CHANGELOG.md b/packages/hooks/CHANGELOG.md index b0918634af..8a934fcd6d 100644 --- a/packages/hooks/CHANGELOG.md +++ b/packages/hooks/CHANGELOG.md @@ -1,5 +1,12 @@ # @sushiswap/hooks +## 3.0.0 + +### Patch Changes + +- Updated dependencies [[`63d4ebe64`](https://github.com/sushiswap/sushiswap/commit/63d4ebe645f546a47401e34f7d2da2d95da6edcb)]: + - sushi@3.1.0 + ## 2.0.0 ### Patch Changes diff --git a/packages/hooks/package.json b/packages/hooks/package.json index b156ca9e54..2eb945dcfc 100644 --- a/packages/hooks/package.json +++ b/packages/hooks/package.json @@ -1,6 +1,6 @@ { "name": "@sushiswap/hooks", - "version": "2.0.0", + "version": "3.0.0", "private": true, "description": "Sushi Hooks", "keywords": [ diff --git a/packages/steer-sdk/CHANGELOG.md b/packages/steer-sdk/CHANGELOG.md new file mode 100644 index 0000000000..a6d8d9e86c --- /dev/null +++ b/packages/steer-sdk/CHANGELOG.md @@ -0,0 +1,9 @@ +# @sushiswap/steer-sdk + +## 0.0.1 + +### Patch Changes + +- Updated dependencies [[`63d4ebe64`](https://github.com/sushiswap/sushiswap/commit/63d4ebe645f546a47401e34f7d2da2d95da6edcb)]: + - sushi@3.1.0 + - @sushiswap/database@0.0.1 diff --git a/packages/steer-sdk/package.json b/packages/steer-sdk/package.json index 01af258689..4fc587b167 100644 --- a/packages/steer-sdk/package.json +++ b/packages/steer-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@sushiswap/steer-sdk", - "version": "0.0.0", + "version": "0.0.1", "description": "Sushi Steer SDK", "keywords": [ "sushi", diff --git a/packages/sushi/CHANGELOG.md b/packages/sushi/CHANGELOG.md index 81492b7efc..a725615009 100644 --- a/packages/sushi/CHANGELOG.md +++ b/packages/sushi/CHANGELOG.md @@ -1,5 +1,11 @@ # sushi +## 3.1.0 + +### Minor Changes + +- [#1598](https://github.com/sushiswap/sushiswap/pull/1598) [`63d4ebe64`](https://github.com/sushiswap/sushiswap/commit/63d4ebe645f546a47401e34f7d2da2d95da6edcb) Thanks [@matthewlilley](https://github.com/matthewlilley)! - configuration + ## 3.0.0 ### Major Changes diff --git a/packages/sushi/package.json b/packages/sushi/package.json index e9ee845f64..aba6e7ed05 100644 --- a/packages/sushi/package.json +++ b/packages/sushi/package.json @@ -1,6 +1,6 @@ { "name": "sushi", - "version": "3.0.0", + "version": "3.1.0", "description": "Sushi", "keywords": [ "sushi" From 6a149b17e875dbfa1da00ed20bf51b40891500a4 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Sat, 10 Aug 2024 12:08:27 +0100 Subject: [PATCH 115/125] chore: rewrite to redirect --- apps/web/next.config.mjs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/apps/web/next.config.mjs b/apps/web/next.config.mjs index e8ff035cb1..b6c9bdcf82 100644 --- a/apps/web/next.config.mjs +++ b/apps/web/next.config.mjs @@ -18,6 +18,16 @@ const nextConfig = bundleAnalyzer({ }, async redirects() { return [ + { + source: '/:path*', + has: [ + { + type: 'host', + value: 'test.sushi.com', + }, + ], + destination: '/test/:path*', + }, { source: '/', permanent: true, From bdea42ad87ad33d6006d41bb67620653c95fca18 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Sat, 10 Aug 2024 12:51:31 +0100 Subject: [PATCH 116/125] fix: changeset script key --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 05ec9c9ccd..16e976f096 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "scripts": { "build": "dotenv -- turbo run build", "changeset": "changeset", - "changeset:release": "changeset publish", + "changeset:publish": "changeset publish", "changeset:version": "changeset version && pnpm install --lockfile-only", "check": "turbo run check --no-cache --filter=!@sushiswap/tines-sandbox --filter=!@sushiswap/route-processor", "clean": "turbo run clean && rm -rf node_modules", From 4b77aa564028eb5218e6210f799699d3ab43b8b9 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Sat, 10 Aug 2024 13:03:52 +0100 Subject: [PATCH 117/125] changesets: ignore everything but sushi pkg --- .changeset/config.json | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/.changeset/config.json b/.changeset/config.json index 1badab8162..69291d7823 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -11,16 +11,38 @@ "baseBranch": "master", "updateInternalDependencies": "patch", "ignore": [ - "@sushiswap/client", - "@sushiswap/react-query", - "@sushiswap/route-processor", - "@sushiswap/storybook", + "@sushiswap/extractor-api", + "@sushiswap/router-api", "@sushiswap/token-list-api", "@sushiswap/tokens-api", + + "@sushiswap/storybook", + "@sushiswap/tron", + "web", + + "eslint-config-sushi", + "@sushiswap/hardhat-config", + "@sushiswap/jest-config", + "@sushiswap/nextjs-config", + "@sushiswap/tailwindcss-config", + "@sushiswap/typescript-config", + "@sushiswap/wagmi-config", + + "@sushiswap/pool-job", + + "@sushiswap/bonds-sdk", + "@sushiswap/client", + "@sushiswap/database", + "@sushiswap/extractor", + "@sushiswap/graph-client", + "@sushiswap/hooks", "@sushiswap/notifications", + "@sushiswap/react-query", + "@sushiswap/steer-sdk", + "@sushiswap/telemetry", "@sushiswap/ui", - "@sushiswap/pool-job", - "@sushiswap/tron", - "web" + + "@sushiswap/route-processor", + "@sushiswap/tines-sandbox" ] } From 9ea2ce108ae1a0b497cee4c3157a3ec211d82601 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Sat, 10 Aug 2024 13:27:27 +0100 Subject: [PATCH 118/125] chore: mark packages as private and tell changeset to ignore --- .changeset/config.json | 4 + apis/extractor/CHANGELOG.md | 9 --- apis/extractor/package.json | 2 +- apis/router/CHANGELOG.md | 9 --- apis/router/package.json | 2 +- config/eslint/CHANGELOG.md | 7 -- config/eslint/package.json | 3 +- config/hardhat/CHANGELOG.md | 27 ------- config/hardhat/package.json | 3 +- config/jest/CHANGELOG.md | 7 -- config/jest/package.json | 3 +- config/nextjs/CHANGELOG.md | 7 -- config/nextjs/package.json | 3 +- config/typescript/CHANGELOG.md | 7 -- config/typescript/package.json | 3 +- config/wagmi/CHANGELOG.md | 32 -------- config/wagmi/package.json | 3 +- packages/bonds-sdk/CHANGELOG.md | 121 ---------------------------- packages/bonds-sdk/package.json | 2 +- packages/client/package.json | 1 + packages/database/CHANGELOG.md | 7 -- packages/database/package.json | 3 +- packages/extractor/CHANGELOG.md | 42 ---------- packages/extractor/package.json | 3 +- packages/graph-client/CHANGELOG.md | 10 --- packages/graph-client/package.json | 3 +- packages/notifications/package.json | 1 + packages/react-query/package.json | 1 + packages/steer-sdk/CHANGELOG.md | 9 --- packages/steer-sdk/package.json | 3 +- packages/telemetry/package.json | 1 + 31 files changed, 31 insertions(+), 307 deletions(-) delete mode 100644 apis/extractor/CHANGELOG.md delete mode 100644 apis/router/CHANGELOG.md delete mode 100644 config/eslint/CHANGELOG.md delete mode 100644 config/hardhat/CHANGELOG.md delete mode 100644 config/jest/CHANGELOG.md delete mode 100644 config/nextjs/CHANGELOG.md delete mode 100644 config/typescript/CHANGELOG.md delete mode 100644 config/wagmi/CHANGELOG.md delete mode 100644 packages/bonds-sdk/CHANGELOG.md delete mode 100644 packages/database/CHANGELOG.md delete mode 100644 packages/extractor/CHANGELOG.md delete mode 100644 packages/graph-client/CHANGELOG.md delete mode 100644 packages/steer-sdk/CHANGELOG.md diff --git a/.changeset/config.json b/.changeset/config.json index 69291d7823..60407dce00 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -10,6 +10,10 @@ "access": "public", "baseBranch": "master", "updateInternalDependencies": "patch", + "privatePackages": { + "tag": false, + "version": false + }, "ignore": [ "@sushiswap/extractor-api", "@sushiswap/router-api", diff --git a/apis/extractor/CHANGELOG.md b/apis/extractor/CHANGELOG.md deleted file mode 100644 index 416d5953c6..0000000000 --- a/apis/extractor/CHANGELOG.md +++ /dev/null @@ -1,9 +0,0 @@ -# @sushiswap/extractor-api - -## 0.0.1 - -### Patch Changes - -- Updated dependencies [[`63d4ebe64`](https://github.com/sushiswap/sushiswap/commit/63d4ebe645f546a47401e34f7d2da2d95da6edcb)]: - - sushi@3.1.0 - - @sushiswap/extractor@1.0.2 diff --git a/apis/extractor/package.json b/apis/extractor/package.json index ba756ccaec..ca142c4dc7 100644 --- a/apis/extractor/package.json +++ b/apis/extractor/package.json @@ -1,6 +1,6 @@ { "name": "@sushiswap/extractor-api", - "version": "0.0.1", + "version": "0.0.0", "private": true, "description": "Sushi Extractor API", "keywords": [ diff --git a/apis/router/CHANGELOG.md b/apis/router/CHANGELOG.md deleted file mode 100644 index 4ed91edddd..0000000000 --- a/apis/router/CHANGELOG.md +++ /dev/null @@ -1,9 +0,0 @@ -# @sushiswap/router-api - -## 0.0.1 - -### Patch Changes - -- Updated dependencies [[`63d4ebe64`](https://github.com/sushiswap/sushiswap/commit/63d4ebe645f546a47401e34f7d2da2d95da6edcb)]: - - sushi@3.1.0 - - @sushiswap/extractor@1.0.2 diff --git a/apis/router/package.json b/apis/router/package.json index 1f5295644a..d3695b934a 100644 --- a/apis/router/package.json +++ b/apis/router/package.json @@ -1,6 +1,6 @@ { "name": "@sushiswap/router-api", - "version": "0.0.1", + "version": "0.0.0", "private": true, "description": "Sushi Router API", "keywords": [ diff --git a/config/eslint/CHANGELOG.md b/config/eslint/CHANGELOG.md deleted file mode 100644 index c85637ccd2..0000000000 --- a/config/eslint/CHANGELOG.md +++ /dev/null @@ -1,7 +0,0 @@ -# @sushiswap/eslint-config - -## 0.1.1 - -### Patch Changes - -- b3761c7c: initial release diff --git a/config/eslint/package.json b/config/eslint/package.json index 9d60d711fb..04be7f218a 100644 --- a/config/eslint/package.json +++ b/config/eslint/package.json @@ -1,6 +1,7 @@ { "name": "eslint-config-sushi", - "version": "0.1.1", + "version": "0.0.0", + "private": true, "description": "Sushi Config", "keywords": [ "sushi", diff --git a/config/hardhat/CHANGELOG.md b/config/hardhat/CHANGELOG.md deleted file mode 100644 index 5a2bb884b9..0000000000 --- a/config/hardhat/CHANGELOG.md +++ /dev/null @@ -1,27 +0,0 @@ -# @sushiswap/hardhat-config - -## 0.1.3 - -### Patch Changes - -- remove the compilation step - -## 0.1.3 - -### Patch Changes - -- [#949](https://github.com/sushiswap/sushiswap/pull/949) [`c6d6cc5db`](https://github.com/sushiswap/sushiswap/commit/c6d6cc5db4cc614f3931ee3a325547967c86c51a) Thanks [@matthewlilley](https://github.com/matthewlilley)! - removes pre-post install scripts - -## 0.1.2 - -### Patch Changes - -- 75972206f: hardhat config embed export type helper -- Updated dependencies [75972206f] - - @sushiswap/types@0.0.2 - -## 0.1.1 - -### Patch Changes - -- b3761c7c: initial release diff --git a/config/hardhat/package.json b/config/hardhat/package.json index f502c7621f..f697e22838 100644 --- a/config/hardhat/package.json +++ b/config/hardhat/package.json @@ -1,6 +1,7 @@ { "name": "@sushiswap/hardhat-config", - "version": "0.1.4", + "version": "0.0.0", + "private": true, "description": "Sushi Hardhat Config", "keywords": [ "sushi", diff --git a/config/jest/CHANGELOG.md b/config/jest/CHANGELOG.md deleted file mode 100644 index 5f81bead55..0000000000 --- a/config/jest/CHANGELOG.md +++ /dev/null @@ -1,7 +0,0 @@ -# @sushiswap/jest-config - -## 0.1.0 - -### Minor Changes - -- b3761c7c: initial release diff --git a/config/jest/package.json b/config/jest/package.json index 8c2a11c324..c2ce88dbb3 100644 --- a/config/jest/package.json +++ b/config/jest/package.json @@ -1,6 +1,7 @@ { "name": "@sushiswap/jest-config", - "version": "0.1.0", + "version": "0.0.0", + "private": true, "description": "Sushi Jest Config", "keywords": [ "sushi", diff --git a/config/nextjs/CHANGELOG.md b/config/nextjs/CHANGELOG.md deleted file mode 100644 index 0af8be1b70..0000000000 --- a/config/nextjs/CHANGELOG.md +++ /dev/null @@ -1,7 +0,0 @@ -# @sushiswap/nextjs-config - -## 0.1.0 - -### Minor Changes - -- b3761c7c: initial release diff --git a/config/nextjs/package.json b/config/nextjs/package.json index 734a418875..8a55cac2f3 100644 --- a/config/nextjs/package.json +++ b/config/nextjs/package.json @@ -1,6 +1,7 @@ { "name": "@sushiswap/nextjs-config", - "version": "0.1.0", + "version": "0.0.0", + "private": true, "description": "Sushi Next.js Config", "keywords": [ "sushi", diff --git a/config/typescript/CHANGELOG.md b/config/typescript/CHANGELOG.md deleted file mode 100644 index f5422c8700..0000000000 --- a/config/typescript/CHANGELOG.md +++ /dev/null @@ -1,7 +0,0 @@ -# @sushiswap/typescript-config - -## 0.1.0 - -### Minor Changes - -- b3761c7c: initial release diff --git a/config/typescript/package.json b/config/typescript/package.json index 4601b2c6b1..d09a22e575 100644 --- a/config/typescript/package.json +++ b/config/typescript/package.json @@ -1,6 +1,7 @@ { "name": "@sushiswap/typescript-config", - "version": "0.1.0", + "version": "0.0.0", + "private": true, "description": "Sushi TypeScript Config", "keywords": [ "sushi", diff --git a/config/wagmi/CHANGELOG.md b/config/wagmi/CHANGELOG.md deleted file mode 100644 index 7972b1628b..0000000000 --- a/config/wagmi/CHANGELOG.md +++ /dev/null @@ -1,32 +0,0 @@ -# @sushiswap/wagmi-config - -## 2.0.0 - -### Patch Changes - -- Updated dependencies [[`63d4ebe64`](https://github.com/sushiswap/sushiswap/commit/63d4ebe645f546a47401e34f7d2da2d95da6edcb)]: - - sushi@3.1.0 - -## 1.0.0 - -### Patch Changes - -- Updated dependencies [[`83d813fb3`](https://github.com/sushiswap/sushiswap/commit/83d813fb338eb5488cbd47513fd525342fbcf81b)]: - - sushi@3.0.0 - -## 0.1.0 - -### Minor Changes - -- b3761c7c: initial release - -### Patch Changes - -- @sushiswap/chain@0.1.0 - -## 0.0.1 - -### Patch Changes - -- Updated dependencies [a38f2e6a] - - @sushiswap/chain@0.1.0 diff --git a/config/wagmi/package.json b/config/wagmi/package.json index 672321c722..c0ab3391e6 100644 --- a/config/wagmi/package.json +++ b/config/wagmi/package.json @@ -1,6 +1,7 @@ { "name": "@sushiswap/wagmi-config", - "version": "2.0.0", + "version": "0.0.0", + "private": true, "description": "Sushi Wagmi Config", "keywords": [ "sushi", diff --git a/packages/bonds-sdk/CHANGELOG.md b/packages/bonds-sdk/CHANGELOG.md deleted file mode 100644 index c9c725b39c..0000000000 --- a/packages/bonds-sdk/CHANGELOG.md +++ /dev/null @@ -1,121 +0,0 @@ -# @sushiswap/v3-sdk - -## 0.0.1 - -### Patch Changes - -- Updated dependencies [[`63d4ebe64`](https://github.com/sushiswap/sushiswap/commit/63d4ebe645f546a47401e34f7d2da2d95da6edcb)]: - - sushi@3.1.0 - -## 1.0.12 - -### Patch Changes - -- Updated dependencies [[`83d813fb3`](https://github.com/sushiswap/sushiswap/commit/83d813fb338eb5488cbd47513fd525342fbcf81b)]: - - sushi@3.0.0 - - @sushiswap/amm@0.1.15 - - @sushiswap/tines@1.0.11 - -## 1.0.11 - -### Patch Changes - -- Updated dependencies [[`2d8510984`](https://github.com/sushiswap/sushiswap/commit/2d85109847583b2cda7ce45c9ffb377043ea46cd)]: - - @sushiswap/currency@0.1.3 - - @sushiswap/amm@0.1.14 - - @sushiswap/tines@1.0.10 - -## 1.0.10 - -### Patch Changes - -- Updated dependencies [[`bc01f18ef`](https://github.com/sushiswap/sushiswap/commit/bc01f18ef532abc44b4b8cfa706f6a1b890ce71d)]: - - @sushiswap/currency@0.1.2 - - @sushiswap/amm@0.1.13 - - @sushiswap/tines@1.0.9 - -## 1.0.9 - -### Patch Changes - -- Updated dependencies [[`dc91c7513`](https://github.com/sushiswap/sushiswap/commit/dc91c7513bee9ca2c505ff4b804e337c98309bb3)]: - - @sushiswap/currency@0.1.1 - - @sushiswap/amm@0.1.12 - - @sushiswap/tines@1.0.8 - -## 1.0.8 - -### Patch Changes - -- Updated dependencies []: - - @sushiswap/amm@0.1.11 - -## 1.0.7 - -### Patch Changes - -- Updated dependencies [[`90784ce08`](https://github.com/sushiswap/sushiswap/commit/90784ce0876741b8f7f41552e181677d0746884b)]: - - @sushiswap/currency@0.1.0 - - @sushiswap/amm@0.1.10 - - @sushiswap/tines@1.0.7 - -## 1.0.6 - -### Patch Changes - -- Updated dependencies [[`c6d6cc5db`](https://github.com/sushiswap/sushiswap/commit/c6d6cc5db4cc614f3931ee3a325547967c86c51a)]: - - @sushiswap/chain@0.1.2 - - @sushiswap/amm@0.1.9 - - @sushiswap/currency@0.0.6 - - @sushiswap/tines@1.0.6 - -## 1.0.5 - -### Patch Changes - -- @sushiswap/amm@0.1.8 - -## 1.0.4 - -### Patch Changes - -- @sushiswap/amm@0.1.7 - -## 1.0.3 - -### Patch Changes - -- @sushiswap/amm@0.1.6 - -## 1.0.2 - -### Patch Changes - -- Updated dependencies [d6b7f8443] - - @sushiswap/chain@0.1.1 - - @sushiswap/amm@0.1.5 - - @sushiswap/currency@0.0.5 - - @sushiswap/tines@1.0.5 - -## 1.0.1 - -### Patch Changes - -- Updated dependencies [813200e55] - - @sushiswap/currency@0.0.4 - - @sushiswap/amm@0.1.4 - - @sushiswap/tines@1.0.4 - -## 1.0.0 - -### Major Changes - -- f083fd9ef: initial release - -## 0.0.1 - -### Patch Changes - -- 074ec9ebc: initial publish chunk -- Updated dependencies [074ec9ebc] - - @sushiswap/amm@0.1.3 diff --git a/packages/bonds-sdk/package.json b/packages/bonds-sdk/package.json index 669547f013..65782852e8 100644 --- a/packages/bonds-sdk/package.json +++ b/packages/bonds-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@sushiswap/bonds-sdk", - "version": "0.0.1", + "version": "0.0.0", "private": true, "description": "Sushi Bonds SDK", "keywords": [ diff --git a/packages/client/package.json b/packages/client/package.json index 5160433de2..93170e0dd1 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,7 @@ { "name": "@sushiswap/client", "version": "0.0.0", + "private": true, "description": "Sushi Client", "keywords": [ "sushi", diff --git a/packages/database/CHANGELOG.md b/packages/database/CHANGELOG.md deleted file mode 100644 index 9304ae3438..0000000000 --- a/packages/database/CHANGELOG.md +++ /dev/null @@ -1,7 +0,0 @@ -# @sushiswap/database - -## 0.0.1 - -### Patch Changes - -- 074ec9ebc: initial publish chunk diff --git a/packages/database/package.json b/packages/database/package.json index e72649d75e..4e21fd826d 100644 --- a/packages/database/package.json +++ b/packages/database/package.json @@ -1,6 +1,7 @@ { "name": "@sushiswap/database", - "version": "0.0.1", + "version": "0.0.0", + "private": true, "description": "Sushi Database", "keywords": [ "sushi", diff --git a/packages/extractor/CHANGELOG.md b/packages/extractor/CHANGELOG.md deleted file mode 100644 index 809f1211d9..0000000000 --- a/packages/extractor/CHANGELOG.md +++ /dev/null @@ -1,42 +0,0 @@ -# @sushiswap/extractor - -## 1.0.2 - -### Patch Changes - -- Updated dependencies [[`63d4ebe64`](https://github.com/sushiswap/sushiswap/commit/63d4ebe645f546a47401e34f7d2da2d95da6edcb)]: - - sushi@3.1.0 - -## 1.0.1 - -### Patch Changes - -- [#1192](https://github.com/sushiswap/sushiswap/pull/1192) [`7d20b6229`](https://github.com/sushiswap/sushiswap/commit/7d20b6229a6393a292a35ff8116df4180314241a) Thanks [@matthewlilley](https://github.com/matthewlilley)! - remove private flags to related depedencies - -- Updated dependencies []: - - @sushiswap/router@0.0.16 - -## 1.0.0 - -### Major Changes - -- [#1190](https://github.com/sushiswap/sushiswap/pull/1190) [`83d813fb3`](https://github.com/sushiswap/sushiswap/commit/83d813fb338eb5488cbd47513fd525342fbcf81b) Thanks [@matthewlilley](https://github.com/matthewlilley)! - extractor v1 release - -### Patch Changes - -- Updated dependencies [[`83d813fb3`](https://github.com/sushiswap/sushiswap/commit/83d813fb338eb5488cbd47513fd525342fbcf81b)]: - - @sushiswap/route-processor-sdk@1.0.0 - - sushi@3.0.0 - - @sushiswap/router-config@3.0.0 - - @sushiswap/amm@0.1.15 - - @sushiswap/router@0.0.15 - - @sushiswap/viem-config@2.0.0 - - @sushiswap/tines@1.0.11 - - @sushiswap/v2-sdk@0.0.11 - - @sushiswap/v3-sdk@1.0.12 - -## 0.1.0 - -### Minor Changes - -- [#1189](https://github.com/sushiswap/sushiswap/pull/1189) [`32d5d2760`](https://github.com/sushiswap/sushiswap/commit/32d5d276098eb0d6bf544f37245cc33f003278ef) Thanks [@matthewlilley](https://github.com/matthewlilley)! - initial release diff --git a/packages/extractor/package.json b/packages/extractor/package.json index 62c85f1f64..dfa6188451 100644 --- a/packages/extractor/package.json +++ b/packages/extractor/package.json @@ -1,6 +1,7 @@ { "name": "@sushiswap/extractor", - "version": "1.0.2", + "version": "0.0.0", + "private": true, "description": "Sushi Extractor", "keywords": [ "sushi", diff --git a/packages/graph-client/CHANGELOG.md b/packages/graph-client/CHANGELOG.md deleted file mode 100644 index 9c85b18f4d..0000000000 --- a/packages/graph-client/CHANGELOG.md +++ /dev/null @@ -1,10 +0,0 @@ -# @sushiswap/graph-client - -## 0.0.1 - -### Patch Changes - -- Updated dependencies [[`63d4ebe64`](https://github.com/sushiswap/sushiswap/commit/63d4ebe645f546a47401e34f7d2da2d95da6edcb)]: - - sushi@3.1.0 - - @sushiswap/bonds-sdk@0.0.1 - - @sushiswap/steer-sdk@0.0.1 diff --git a/packages/graph-client/package.json b/packages/graph-client/package.json index 32330c3a84..85bcce2e5c 100644 --- a/packages/graph-client/package.json +++ b/packages/graph-client/package.json @@ -1,6 +1,7 @@ { "name": "@sushiswap/graph-client", - "version": "0.0.1", + "version": "0.0.0", + "private": true, "description": "Graph Client", "keywords": [ "sushi", diff --git a/packages/notifications/package.json b/packages/notifications/package.json index 1da08d1503..57fc7cfa22 100644 --- a/packages/notifications/package.json +++ b/packages/notifications/package.json @@ -1,6 +1,7 @@ { "name": "@sushiswap/notifications", "version": "0.0.0", + "private": true, "description": "Sushi Notifications", "keywords": [ "sushi", diff --git a/packages/react-query/package.json b/packages/react-query/package.json index 2bbcbceaef..c5daee12a9 100644 --- a/packages/react-query/package.json +++ b/packages/react-query/package.json @@ -1,6 +1,7 @@ { "name": "@sushiswap/react-query", "version": "0.0.0", + "private": true, "description": "Sushi React Query", "keywords": [ "sushi", diff --git a/packages/steer-sdk/CHANGELOG.md b/packages/steer-sdk/CHANGELOG.md deleted file mode 100644 index a6d8d9e86c..0000000000 --- a/packages/steer-sdk/CHANGELOG.md +++ /dev/null @@ -1,9 +0,0 @@ -# @sushiswap/steer-sdk - -## 0.0.1 - -### Patch Changes - -- Updated dependencies [[`63d4ebe64`](https://github.com/sushiswap/sushiswap/commit/63d4ebe645f546a47401e34f7d2da2d95da6edcb)]: - - sushi@3.1.0 - - @sushiswap/database@0.0.1 diff --git a/packages/steer-sdk/package.json b/packages/steer-sdk/package.json index 4fc587b167..4f6895b65b 100644 --- a/packages/steer-sdk/package.json +++ b/packages/steer-sdk/package.json @@ -1,6 +1,7 @@ { "name": "@sushiswap/steer-sdk", - "version": "0.0.1", + "version": "0.0.0", + "private": true, "description": "Sushi Steer SDK", "keywords": [ "sushi", diff --git a/packages/telemetry/package.json b/packages/telemetry/package.json index ed4f25fbd7..06c508865d 100644 --- a/packages/telemetry/package.json +++ b/packages/telemetry/package.json @@ -1,6 +1,7 @@ { "name": "@sushiswap/telemetry", "version": "0.0.0", + "private": true, "description": "Sushi Telemetry", "keywords": [ "sushi", From e8fb35fe961dae208b73c786238adbbec75fb597 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Sat, 10 Aug 2024 13:49:18 +0100 Subject: [PATCH 119/125] fix: redirect --- apps/web/next.config.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/web/next.config.mjs b/apps/web/next.config.mjs index b6c9bdcf82..9c6c4cf9e3 100644 --- a/apps/web/next.config.mjs +++ b/apps/web/next.config.mjs @@ -27,6 +27,7 @@ const nextConfig = bundleAnalyzer({ }, ], destination: '/test/:path*', + permanent: true, }, { source: '/', From 1e2a62ca19cbeceffa90ce9b0838c993d175a8c3 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Sat, 10 Aug 2024 14:46:46 +0100 Subject: [PATCH 120/125] chore: aptos redirect --- apps/web/next.config.mjs | 68 +++++++++++----------------------------- 1 file changed, 18 insertions(+), 50 deletions(-) diff --git a/apps/web/next.config.mjs b/apps/web/next.config.mjs index 9c6c4cf9e3..21d691139d 100644 --- a/apps/web/next.config.mjs +++ b/apps/web/next.config.mjs @@ -26,9 +26,25 @@ const nextConfig = bundleAnalyzer({ value: 'test.sushi.com', }, ], - destination: '/test/:path*', + destination: '/test/swap', permanent: true, }, + { + source: '/:path*', + has: [ + { + type: 'host', + value: 'aptos.sushi.com', + }, + ], + destination: '/aptos', + permanent: true, + }, + { + source: '/aptos', + permanent: true, + destination: '/aptos/swap', + }, { source: '/', permanent: true, @@ -74,63 +90,15 @@ const nextConfig = bundleAnalyzer({ permanent: true, destination: '/pool/:path*', }, - { - source: '/aptos', - permanent: true, - destination: '/aptos/swap', - }, { source: '/skale/swap', permanent: true, destination: '/swap?chainId=2046399126', }, - { - source: '/furo', - permanent: true, - destination: `${FURO_URL}`, - }, - { - source: '/furo/:path*', - permanent: true, - destination: `${FURO_URL}/:path*`, - }, ] }, async rewrites() { - return [ - // if the host is `aptos.sushi.com`, - // this rewrite will be applied - // { - // source: '/:path*', - // has: [ - // { - // type: 'host', - // value: 'aptos.sushi.com', - // }, - // ], - // destination: '/aptos/:path*', - // }, - { - source: '/:path*', - has: [ - { - type: 'host', - value: 'test.sushi.com', - }, - ], - destination: '/test/:path*', - }, - // { - // source: '/:path*', - // has: [ - // { - // type: 'host', - // value: 'pay.sushi.com', - // }, - // ], - // destination: '/pay/:path*', - // }, - ] + return [] }, }) From 33cb4a9088ace18d6d0ffb155445eb69ea7618a3 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Sat, 10 Aug 2024 15:04:15 +0100 Subject: [PATCH 121/125] fix: redirect --- apps/web/next.config.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/web/next.config.mjs b/apps/web/next.config.mjs index 21d691139d..7e006259a8 100644 --- a/apps/web/next.config.mjs +++ b/apps/web/next.config.mjs @@ -26,7 +26,7 @@ const nextConfig = bundleAnalyzer({ value: 'test.sushi.com', }, ], - destination: '/test/swap', + destination: 'https://sushi.com/test/:path*', permanent: true, }, { @@ -37,7 +37,7 @@ const nextConfig = bundleAnalyzer({ value: 'aptos.sushi.com', }, ], - destination: '/aptos', + destination: 'https://sushi.com/aptos/:path*', permanent: true, }, { From 67ddb03ee43df385d4271e46d352862a4c7cc1a1 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Sat, 10 Aug 2024 15:15:48 +0100 Subject: [PATCH 122/125] chore: remove unused rpc urls from wagmi config --- config/wagmi/src/rpc-urls.ts | 66 ------------------------------------ 1 file changed, 66 deletions(-) delete mode 100644 config/wagmi/src/rpc-urls.ts diff --git a/config/wagmi/src/rpc-urls.ts b/config/wagmi/src/rpc-urls.ts deleted file mode 100644 index 41fb25012d..0000000000 --- a/config/wagmi/src/rpc-urls.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { ChainId } from 'sushi/chain' - -const drpcId = process.env['DRPC_ID'] || process.env['NEXT_PUBLIC_DRPC_ID'] - -export const rpcUrls = { - [ChainId.ARBITRUM_NOVA]: [ - `https://lb.drpc.org/ogrpc?network=arbitrum-nova&dkey=${drpcId}`, - ], - [ChainId.ARBITRUM]: [ - `https://lb.drpc.org/ogrpc?network=arbitrum&dkey=${drpcId}`, - ], - [ChainId.AVALANCHE]: [ - `https://lb.drpc.org/ogrpc?network=avalanche&dkey=${drpcId}`, - ], - [ChainId.BASE]: [`https://lb.drpc.org/ogrpc?network=base&dkey=${drpcId}`], - [ChainId.BOBA]: ['https://mainnet.boba.network'], - [ChainId.BOBA_BNB]: ['https://bnb.boba.network'], - [ChainId.BSC]: [`https://lb.drpc.org/ogrpc?network=bsc&dkey=${drpcId}`], - [ChainId.BTTC]: ['https://rpc.bittorrentchain.io'], - [ChainId.CELO]: [`https://lb.drpc.org/ogrpc?network=celo&dkey=${drpcId}`], - [ChainId.ETHEREUM]: [ - `https://lb.drpc.org/ogrpc?network=ethereum&dkey=${drpcId}`, - ], - [ChainId.FANTOM]: [`https://lb.drpc.org/ogrpc?network=fantom&dkey=${drpcId}`], - [ChainId.FILECOIN]: [ - `https://lb.drpc.org/ogrpc?network=filecoin&dkey=${drpcId}`, - ], - // [ChainId.FILECOIN]: ['https://fil-mainnet-1.rpc.laconic.com/rpc/v1'], - [ChainId.FUSE]: [`https://lb.drpc.org/ogrpc?network=fuse&dkey=${drpcId}`], - [ChainId.GNOSIS]: [`https://lb.drpc.org/ogrpc?network=gnosis&dkey=${drpcId}`], - [ChainId.HARMONY]: [ - `https://lb.drpc.org/ogrpc?network=harmony-0&dkey=${drpcId}`, - ], - [ChainId.KAVA]: [`https://lb.drpc.org/ogrpc?network=kava&dkey=${drpcId}`], - [ChainId.METIS]: [`https://lb.drpc.org/ogrpc?network=metis&dkey=${drpcId}`], - [ChainId.MOONBEAM]: [ - `https://lb.drpc.org/ogrpc?network=moonbeam&dkey=${drpcId}`, - ], - [ChainId.MOONRIVER]: [ - `https://lb.drpc.org/ogrpc?network=moonriver&dkey=${drpcId}`, - ], - [ChainId.OPTIMISM]: [ - `https://lb.drpc.org/ogrpc?network=optimism&dkey=${drpcId}`, - ], - [ChainId.POLYGON]: [ - `https://lb.drpc.org/ogrpc?network=polygon&dkey=${drpcId}`, - ], - [ChainId.POLYGON_ZKEVM]: [ - `https://lb.drpc.org/ogrpc?network=polygon-zkevm&dkey=${drpcId}`, - ], - [ChainId.THUNDERCORE]: ['https://mainnet-rpc.thundercore.com'], - [ChainId.HAQQ]: [`https://lb.drpc.org/ogrpc?network=haqq&dkey=${drpcId}`], - [ChainId.CORE]: ['https://rpc.coredao.org'], - [ChainId.TELOS]: ['https://rpc1.us.telos.net/evm'], - [ChainId.LINEA]: [`https://lb.drpc.org/ogrpc?network=linea&dkey=${drpcId}`], - [ChainId.SCROLL]: [`https://lb.drpc.org/ogrpc?network=scroll&dkey=${drpcId}`], - [ChainId.ZETACHAIN]: [ - 'https://zetachain-mainnet-archive.allthatnode.com:8545', - ], - [ChainId.CRONOS]: [`https://lb.drpc.org/ogrpc?network=cronos&dkey=${drpcId}`], - [ChainId.BLAST]: [`https://lb.drpc.org/ogrpc?network=blast&dkey=${drpcId}`], - [ChainId.SKALE_EUROPA]: ['https://mainnet.skalenodes.com/v1/elated-tan-skat'], - [ChainId.ROOTSTOCK]: ['https://public-node.rsk.co'], -} as const - -export type RpcEnabledChainId = keyof typeof rpcUrls From c99584bd50eaf979667137dc06b4c267a6c32290 Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Sat, 10 Aug 2024 15:28:38 +0100 Subject: [PATCH 123/125] chore: remove wagmi config pkg --- .changeset/config.json | 1 - apis/tokens/lib/api.ts | 16 +- apis/tokens/lib/api/v2.ts | 6 +- apis/tokens/package.json | 1 - apps/web/next.config.mjs | 2 - apps/web/package.json | 1 - .../balance/v0/[chainId]/[address]/route.ts | 2 +- .../faucet/skale-europa/[address]/route.ts | 4 +- .../(evm)/claims/rp2/check-approvals/route.ts | 2 +- apps/web/src/lib/db.ts | 2 +- .../src/lib/hooks/api/useSkaleEuropaFaucet.ts | 2 +- .../account/AddressToEnsResolver.tsx | 2 +- .../account/EnsToAddressResolver.tsx | 2 +- apps/web/src/lib/wagmi/config/index.ts | 2 +- apps/web/src/lib/wagmi/config/production.ts | 4 +- .../web/src/lib/wagmi/config/public.ts | 0 .../approvals/actions/getTokenAllowance.ts | 2 +- .../bentobox/actions/getBentoboxTotal.ts | 3 +- .../bentobox/actions/getBentoboxTotals.ts | 2 +- .../hooks/bentobox/hooks/useBentoBoxTotals.ts | 3 +- .../lib/wagmi/hooks/contracts/multicall3.ts | 2 +- .../actions/getConcentratedLiquidityPool.ts | 5 +- .../getConcentratedLiquidityPoolReserves.ts | 4 +- .../actions/getConcentratedPositionOwner.ts | 3 +- .../pools/actions/getSushiSwapV2Pools.ts | 2 +- .../wagmi/hooks/pools/actions/getV3Pools.ts | 2 +- .../src/lib/wagmi/hooks/pools/types/index.ts | 4 +- .../getConcentratedLiquidityPositionFees.ts | 2 +- .../getConcentratedLiquidityPositions.ts | 5 +- ...centratedLiquidityPositionsFromTokenIds.ts | 5 +- .../wagmi/hooks/tokens/useTokenWithCache.ts | 2 +- apps/web/src/lib/wagmi/index.ts | 2 +- config/wagmi/README.md | 3 - config/wagmi/package.json | 66 ------ config/wagmi/tsconfig.json | 12 - jobs/pool/package.json | 1 - jobs/pool/src/lib/wagmi.ts | 12 +- pnpm-lock.yaml | 219 ++++++------------ 38 files changed, 121 insertions(+), 289 deletions(-) rename config/wagmi/src/index.ts => apps/web/src/lib/wagmi/config/public.ts (100%) delete mode 100644 config/wagmi/README.md delete mode 100644 config/wagmi/package.json delete mode 100644 config/wagmi/tsconfig.json diff --git a/.changeset/config.json b/.changeset/config.json index 60407dce00..5f561a1e8e 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -30,7 +30,6 @@ "@sushiswap/nextjs-config", "@sushiswap/tailwindcss-config", "@sushiswap/typescript-config", - "@sushiswap/wagmi-config", "@sushiswap/pool-job", diff --git a/apis/tokens/lib/api.ts b/apis/tokens/lib/api.ts index 4c0982fe43..91ed33897c 100644 --- a/apis/tokens/lib/api.ts +++ b/apis/tokens/lib/api.ts @@ -1,10 +1,18 @@ import { createClient } from '@sushiswap/database' -import { publicWagmiConfig } from '@sushiswap/wagmi-config' import { createConfig, getToken as getTokenFromContract } from '@wagmi/core' -import { ChainId } from 'sushi' +import { ChainId } from 'sushi/chain' +import { publicChains, publicTransports } from 'sushi/config' import { type Address } from 'viem' -const config = createConfig(publicWagmiConfig) +export const config = { + chains: publicChains, + transports: publicTransports, + batch: { + multicall: { + wait: 64, + }, + }, +} as const satisfies Parameters[0] // import * as defaultTokenList from '@sushiswap/default-token-list' assert { type: 'json' } @@ -41,7 +49,7 @@ export async function getToken(chainId: number, address: string) { return token } catch { await client.$disconnect() - const tokenFromContract = await getTokenFromContract(config, { + const tokenFromContract = await getTokenFromContract(createConfig(config), { chainId: chainId as ChainId, address: address as Address, }).catch(() => { diff --git a/apis/tokens/lib/api/v2.ts b/apis/tokens/lib/api/v2.ts index 38e004fd12..18ac0ac69f 100644 --- a/apis/tokens/lib/api/v2.ts +++ b/apis/tokens/lib/api/v2.ts @@ -1,13 +1,11 @@ -import { publicWagmiConfig } from '@sushiswap/wagmi-config' import { createConfig, fetchToken } from '@wagmi/core' import { sql } from 'drizzle-orm' import type { ChainId } from 'sushi/chain' import { type Address, getAddress } from 'viem' +import { config } from '../api.js' import { databaseClient, tokenSchema } from '../db.js' export async function getToken(chainId: ChainId, address: string) { - const config = createConfig(publicWagmiConfig) - try { const tokens = await databaseClient .select({ @@ -33,7 +31,7 @@ export async function getToken(chainId: ChainId, address: string) { address: getAddress(token.address), } } catch { - const tokenFromContract = await fetchToken(config, { + const tokenFromContract = await fetchToken(createConfig(config), { chainId, address: address as Address, }).catch(() => { diff --git a/apis/tokens/package.json b/apis/tokens/package.json index 82fbcb9736..0b532f436a 100644 --- a/apis/tokens/package.json +++ b/apis/tokens/package.json @@ -27,7 +27,6 @@ "@neondatabase/serverless": "^0.9.0", "@sushiswap/database": "workspace:*", "@sushiswap/default-token-list": "^43.1.0", - "@sushiswap/wagmi-config": "workspace:*", "@upstash/redis": "1.22.1", "@vercel/node": "3.0.9", "@wagmi/core": "2.13.1", diff --git a/apps/web/next.config.mjs b/apps/web/next.config.mjs index 7e006259a8..9ce2d61dd1 100644 --- a/apps/web/next.config.mjs +++ b/apps/web/next.config.mjs @@ -7,8 +7,6 @@ const bundleAnalyzer = withBundleAnalyzer({ enabled: false && process.env.NODE_ENV !== 'development', }) -const FURO_URL = 'https://pay.sushi.com' - /** @type {import('next').NextConfig} */ const nextConfig = bundleAnalyzer({ ...defaultNextConfig, diff --git a/apps/web/package.json b/apps/web/package.json index 5d0fae548f..2c7afb5cc5 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -50,7 +50,6 @@ "@sushiswap/tailwindcss-config": "workspace:*", "@sushiswap/telemetry": "workspace:*", "@sushiswap/ui": "workspace:*", - "@sushiswap/wagmi-config": "workspace:*", "@tanstack/react-query": "5.51.16", "@tanstack/react-query-devtools": "4.28.0", "@tanstack/react-query-persist-client": "4.28.0", diff --git a/apps/web/src/app/(evm)/api/balance/v0/[chainId]/[address]/route.ts b/apps/web/src/app/(evm)/api/balance/v0/[chainId]/[address]/route.ts index 5bee0b7136..4c436f0ac5 100644 --- a/apps/web/src/app/(evm)/api/balance/v0/[chainId]/[address]/route.ts +++ b/apps/web/src/app/(evm)/api/balance/v0/[chainId]/[address]/route.ts @@ -1,11 +1,11 @@ // import { ChainID as CovalentChainID } from '@covalenthq/client-sdk' -import { publicWagmiConfig } from '@sushiswap/wagmi-config' import { createConfig, getBalance, readContracts } from '@wagmi/core' import zip from 'lodash.zip' // import { covalentClient } from 'src/lib/covalent' import { type ChainId } from 'sushi/chain' import { Address, erc20Abi } from 'viem' import { z } from 'zod' +import { publicWagmiConfig } from '../../../../../../../lib/wagmi/config/public' const config = createConfig(publicWagmiConfig) diff --git a/apps/web/src/app/(evm)/api/faucet/skale-europa/[address]/route.ts b/apps/web/src/app/(evm)/api/faucet/skale-europa/[address]/route.ts index 72bdd3d65c..664f048917 100644 --- a/apps/web/src/app/(evm)/api/faucet/skale-europa/[address]/route.ts +++ b/apps/web/src/app/(evm)/api/faucet/skale-europa/[address]/route.ts @@ -1,4 +1,3 @@ -import { publicWagmiConfig } from '@sushiswap/wagmi-config' import { SendTransactionParameters, createConfig, @@ -8,10 +7,11 @@ import { sendTransaction, } from '@wagmi/core' import { NextRequest, NextResponse } from 'next/server' -import { ChainId } from 'sushi' +import { ChainId } from 'sushi/chain' import { Hex, getAddress } from 'viem' import { privateKeyToAccount } from 'viem/accounts' import { z } from 'zod' +import { publicWagmiConfig } from '../../../../../../lib/wagmi/config/public' const MAX_BALANCE_AMOUNT = 100000000000n // 0.0000001 const DISTRIBUTION_AMOUNT = 5000000000000n // 0.000005 diff --git a/apps/web/src/app/(evm)/claims/rp2/check-approvals/route.ts b/apps/web/src/app/(evm)/claims/rp2/check-approvals/route.ts index b5346608e1..3dafb32ee7 100644 --- a/apps/web/src/app/(evm)/claims/rp2/check-approvals/route.ts +++ b/apps/web/src/app/(evm)/claims/rp2/check-approvals/route.ts @@ -1,4 +1,3 @@ -import { publicWagmiConfig } from '@sushiswap/wagmi-config' import { RouteProcessor2ChainId } from 'sushi/config' import { getIdFromChainIdAddress } from 'sushi/format' import type { Token } from 'sushi/types' @@ -8,6 +7,7 @@ import { getToken } from 'wagmi/actions' import { z } from 'zod' import rp2Approvals from 'src/lib/wagmi/hooks/exploits/data/rp2-approvals.json' +import { publicWagmiConfig } from '../../../../../lib/wagmi/config/public' const querySchema = z.object({ account: z.coerce.string().transform((account) => account as Address), diff --git a/apps/web/src/lib/db.ts b/apps/web/src/lib/db.ts index ffdbc32bee..ea5ab024bb 100644 --- a/apps/web/src/lib/db.ts +++ b/apps/web/src/lib/db.ts @@ -1,9 +1,9 @@ import { createClient } from '@sushiswap/database' -import { publicWagmiConfig } from '@sushiswap/wagmi-config' import { createConfig } from '@wagmi/core' import { getToken as getTokenFromContract } from '@wagmi/core/actions' import { ChainId } from 'sushi/chain' import { Address } from 'viem' +import { publicWagmiConfig } from './wagmi/config/public' // import * as defaultTokenList from '@sushiswap/default-token-list' assert { type: 'json' } const config = createConfig(publicWagmiConfig) diff --git a/apps/web/src/lib/hooks/api/useSkaleEuropaFaucet.ts b/apps/web/src/lib/hooks/api/useSkaleEuropaFaucet.ts index a5aa30dc70..047952e3e7 100644 --- a/apps/web/src/lib/hooks/api/useSkaleEuropaFaucet.ts +++ b/apps/web/src/lib/hooks/api/useSkaleEuropaFaucet.ts @@ -1,11 +1,11 @@ 'use client' -import { publicWagmiConfig } from '@sushiswap/wagmi-config' import { useQuery } from '@tanstack/react-query' import { createConfig, getBalance } from '@wagmi/core' import { ChainId } from 'sushi/chain' import { Address } from 'viem' import { useAccount } from 'wagmi' +import { publicWagmiConfig } from '../../wagmi/config/public' const MAX_BALANCE_AMOUNT = 100000000000n // '0.0000001' diff --git a/apps/web/src/lib/wagmi/components/account/AddressToEnsResolver.tsx b/apps/web/src/lib/wagmi/components/account/AddressToEnsResolver.tsx index ea6350665c..77532a4f06 100644 --- a/apps/web/src/lib/wagmi/components/account/AddressToEnsResolver.tsx +++ b/apps/web/src/lib/wagmi/components/account/AddressToEnsResolver.tsx @@ -1,7 +1,7 @@ -import { PublicWagmiConfig } from '@sushiswap/wagmi-config' import { ReactNode } from 'react' import { ChainId } from 'sushi/chain' import { useEnsName } from 'wagmi' +import { PublicWagmiConfig } from '../../config/public' export type Props = Parameters>[0] & { children: diff --git a/apps/web/src/lib/wagmi/components/account/EnsToAddressResolver.tsx b/apps/web/src/lib/wagmi/components/account/EnsToAddressResolver.tsx index 8c31a0054c..d3e9d8f7bd 100644 --- a/apps/web/src/lib/wagmi/components/account/EnsToAddressResolver.tsx +++ b/apps/web/src/lib/wagmi/components/account/EnsToAddressResolver.tsx @@ -1,7 +1,7 @@ -import { PublicWagmiConfig } from '@sushiswap/wagmi-config' import { ReactNode } from 'react' import { ChainId } from 'sushi/chain' import { useEnsAddress } from 'wagmi' +import { PublicWagmiConfig } from '../../config/public' export type Props = Parameters>[0] & { children: diff --git a/apps/web/src/lib/wagmi/config/index.ts b/apps/web/src/lib/wagmi/config/index.ts index 576fd20eb4..2c89c44b48 100644 --- a/apps/web/src/lib/wagmi/config/index.ts +++ b/apps/web/src/lib/wagmi/config/index.ts @@ -1,8 +1,8 @@ 'use client' -import { PublicWagmiConfig } from '@sushiswap/wagmi-config' import { cookieToInitialState } from '@wagmi/core' import { createProductionConfig } from './production' +import { PublicWagmiConfig } from './public' import { createTestConfig } from './test' export { createProductionConfig } diff --git a/apps/web/src/lib/wagmi/config/production.ts b/apps/web/src/lib/wagmi/config/production.ts index b959cf3202..f7c689490b 100644 --- a/apps/web/src/lib/wagmi/config/production.ts +++ b/apps/web/src/lib/wagmi/config/production.ts @@ -11,11 +11,11 @@ import { walletConnectWallet, } from '@rainbow-me/rainbowkit/wallets' import { gtagEvent } from '@sushiswap/ui' -import { publicWagmiConfig } from '@sushiswap/wagmi-config' -import { ChainId } from 'sushi' +import { ChainId } from 'sushi/chain' import { publicTransports } from 'sushi/config' import { http, cookieStorage, createConfig, createStorage } from 'wagmi' import { Writeable } from 'zod' +import { publicWagmiConfig } from './public' export const DEFAULT_POLLING_INTERVAL = 4_000 diff --git a/config/wagmi/src/index.ts b/apps/web/src/lib/wagmi/config/public.ts similarity index 100% rename from config/wagmi/src/index.ts rename to apps/web/src/lib/wagmi/config/public.ts diff --git a/apps/web/src/lib/wagmi/hooks/approvals/actions/getTokenAllowance.ts b/apps/web/src/lib/wagmi/hooks/approvals/actions/getTokenAllowance.ts index 4f3a49d011..e9e2cf21ab 100644 --- a/apps/web/src/lib/wagmi/hooks/approvals/actions/getTokenAllowance.ts +++ b/apps/web/src/lib/wagmi/hooks/approvals/actions/getTokenAllowance.ts @@ -1,8 +1,8 @@ -import { PublicWagmiConfig } from '@sushiswap/wagmi-config' import { readContract } from '@wagmi/core' import { ChainId } from 'sushi/chain' import { Amount, Token } from 'sushi/currency' import { Address, erc20Abi } from 'viem' +import { PublicWagmiConfig } from '../../../config/public' interface GetTokenAllowance { chainId: ChainId diff --git a/apps/web/src/lib/wagmi/hooks/bentobox/actions/getBentoboxTotal.ts b/apps/web/src/lib/wagmi/hooks/bentobox/actions/getBentoboxTotal.ts index bf5f066057..3091870f47 100644 --- a/apps/web/src/lib/wagmi/hooks/bentobox/actions/getBentoboxTotal.ts +++ b/apps/web/src/lib/wagmi/hooks/bentobox/actions/getBentoboxTotal.ts @@ -1,7 +1,6 @@ import { BentoBoxChainId } from 'sushi/config' import { Type } from 'sushi/currency' - -import { PublicWagmiConfig } from '@sushiswap/wagmi-config' +import { PublicWagmiConfig } from '../../../config/public' import { getBentoboxTotals } from './getBentoboxTotals' export const getBentoboxTotal = async ({ diff --git a/apps/web/src/lib/wagmi/hooks/bentobox/actions/getBentoboxTotals.ts b/apps/web/src/lib/wagmi/hooks/bentobox/actions/getBentoboxTotals.ts index 23b3cc47eb..8be374d3b3 100644 --- a/apps/web/src/lib/wagmi/hooks/bentobox/actions/getBentoboxTotals.ts +++ b/apps/web/src/lib/wagmi/hooks/bentobox/actions/getBentoboxTotals.ts @@ -1,10 +1,10 @@ -import { PublicWagmiConfig } from '@sushiswap/wagmi-config' import { readContracts } from '@wagmi/core' import { Rebase } from 'sushi' import { bentoBoxV1TotalsAbi } from 'sushi/abi' import { BENTOBOX_ADDRESS, BentoBoxChainId } from 'sushi/config' import { Type as Currency } from 'sushi/currency' import { Address } from 'viem' +import { PublicWagmiConfig } from '../../../config/public' const totalsMap = new Map() diff --git a/apps/web/src/lib/wagmi/hooks/bentobox/hooks/useBentoBoxTotals.ts b/apps/web/src/lib/wagmi/hooks/bentobox/hooks/useBentoBoxTotals.ts index b58fb2ef7d..54e6660bc4 100644 --- a/apps/web/src/lib/wagmi/hooks/bentobox/hooks/useBentoBoxTotals.ts +++ b/apps/web/src/lib/wagmi/hooks/bentobox/hooks/useBentoBoxTotals.ts @@ -4,9 +4,8 @@ import { useQuery } from '@tanstack/react-query' import { ChainId } from 'sushi/chain' import { isBentoBoxChainId } from 'sushi/config' import { Type } from 'sushi/currency' - -import { PublicWagmiConfig } from '@sushiswap/wagmi-config' import { useConfig } from 'wagmi' +import { PublicWagmiConfig } from '../../../config/public' import { getBentoboxTotals } from '../actions/getBentoboxTotals' interface UseBentoboxTotalsParams { diff --git a/apps/web/src/lib/wagmi/hooks/contracts/multicall3.ts b/apps/web/src/lib/wagmi/hooks/contracts/multicall3.ts index a02c6c375e..1229f0774e 100644 --- a/apps/web/src/lib/wagmi/hooks/contracts/multicall3.ts +++ b/apps/web/src/lib/wagmi/hooks/contracts/multicall3.ts @@ -1,7 +1,7 @@ 'use client' -import { publicWagmiConfig } from '@sushiswap/wagmi-config' import { Address } from 'viem' +import { publicWagmiConfig } from '../../config/public' export type Multicall3ChainId = (typeof publicWagmiConfig)['chains'][number]['id'] diff --git a/apps/web/src/lib/wagmi/hooks/pools/actions/getConcentratedLiquidityPool.ts b/apps/web/src/lib/wagmi/hooks/pools/actions/getConcentratedLiquidityPool.ts index dc24af6328..279ce5777f 100644 --- a/apps/web/src/lib/wagmi/hooks/pools/actions/getConcentratedLiquidityPool.ts +++ b/apps/web/src/lib/wagmi/hooks/pools/actions/getConcentratedLiquidityPool.ts @@ -1,3 +1,4 @@ +import { readContracts } from '@wagmi/core/actions' import { SUSHISWAP_V3_FACTORY_ADDRESS, SushiSwapV3ChainId, @@ -8,10 +9,8 @@ import { SushiSwapV3Pool, computeSushiSwapV3PoolAddress, } from 'sushi/pool/sushiswap-v3' - -import { PublicWagmiConfig } from '@sushiswap/wagmi-config' -import { readContracts } from '@wagmi/core/actions' import { Address } from 'viem' +import { PublicWagmiConfig } from '../../../config/public' export const getConcentratedLiquidityPools = async ({ chainId, diff --git a/apps/web/src/lib/wagmi/hooks/pools/actions/getConcentratedLiquidityPoolReserves.ts b/apps/web/src/lib/wagmi/hooks/pools/actions/getConcentratedLiquidityPoolReserves.ts index d5a0e4662a..41683391ff 100644 --- a/apps/web/src/lib/wagmi/hooks/pools/actions/getConcentratedLiquidityPoolReserves.ts +++ b/apps/web/src/lib/wagmi/hooks/pools/actions/getConcentratedLiquidityPoolReserves.ts @@ -1,12 +1,12 @@ +import { getBalance } from '@wagmi/core' import { SUSHISWAP_V3_FACTORY_ADDRESS, SushiSwapV3ChainId } from 'sushi/config' import { Amount } from 'sushi/currency' import { SushiSwapV3Pool, computeSushiSwapV3PoolAddress, } from 'sushi/pool/sushiswap-v3' +import { PublicWagmiConfig } from '../../../config/public' -import { PublicWagmiConfig } from '@sushiswap/wagmi-config' -import { getBalance } from '@wagmi/core' export const getConcentratedLiquidityPoolReserves = async ({ pool, chainId, diff --git a/apps/web/src/lib/wagmi/hooks/pools/actions/getConcentratedPositionOwner.ts b/apps/web/src/lib/wagmi/hooks/pools/actions/getConcentratedPositionOwner.ts index 7809639b21..b19e56cb38 100644 --- a/apps/web/src/lib/wagmi/hooks/pools/actions/getConcentratedPositionOwner.ts +++ b/apps/web/src/lib/wagmi/hooks/pools/actions/getConcentratedPositionOwner.ts @@ -1,7 +1,6 @@ import { SUSHISWAP_V3_POSTIION_MANAGER, SushiSwapV3ChainId } from 'sushi/config' - -import { PublicWagmiConfig } from '@sushiswap/wagmi-config' import { readContracts } from 'wagmi/actions' +import { PublicWagmiConfig } from '../../../config/public' export const getConcentratedPositionOwners = async ({ tokenIds, diff --git a/apps/web/src/lib/wagmi/hooks/pools/actions/getSushiSwapV2Pools.ts b/apps/web/src/lib/wagmi/hooks/pools/actions/getSushiSwapV2Pools.ts index 373babd3a0..b14d6dff96 100644 --- a/apps/web/src/lib/wagmi/hooks/pools/actions/getSushiSwapV2Pools.ts +++ b/apps/web/src/lib/wagmi/hooks/pools/actions/getSushiSwapV2Pools.ts @@ -1,4 +1,3 @@ -import { PublicWagmiConfig } from '@sushiswap/wagmi-config' import { readContracts } from '@wagmi/core/actions' import { uniswapV2PairAbi } from 'sushi/abi' import { @@ -11,6 +10,7 @@ import { SushiSwapV2Pool, computeSushiSwapV2PoolAddress, } from 'sushi/pool/sushiswap-v2' +import { PublicWagmiConfig } from '../../../config/public' export enum PairState { LOADING = 'Loading', diff --git a/apps/web/src/lib/wagmi/hooks/pools/actions/getV3Pools.ts b/apps/web/src/lib/wagmi/hooks/pools/actions/getV3Pools.ts index 442b2e8e3f..7a5b38cb6d 100644 --- a/apps/web/src/lib/wagmi/hooks/pools/actions/getV3Pools.ts +++ b/apps/web/src/lib/wagmi/hooks/pools/actions/getV3Pools.ts @@ -1,4 +1,3 @@ -import { PublicWagmiConfig } from '@sushiswap/wagmi-config' import { readContracts } from '@wagmi/core/actions' import { erc20Abi } from 'sushi/abi' import { uniswapV3PoolAbi } from 'sushi/abi' @@ -13,6 +12,7 @@ import { Currency, Token, Type } from 'sushi/currency' import { computeSushiSwapV3PoolAddress } from 'sushi/pool/sushiswap-v3' import { RToken, UniV3Pool } from 'sushi/tines' import { Address } from 'viem' +import { PublicWagmiConfig } from '../../../config/public' export enum V3PoolState { LOADING = 'Loading', diff --git a/apps/web/src/lib/wagmi/hooks/pools/types/index.ts b/apps/web/src/lib/wagmi/hooks/pools/types/index.ts index 56c255bef5..0f2e9b5aca 100644 --- a/apps/web/src/lib/wagmi/hooks/pools/types/index.ts +++ b/apps/web/src/lib/wagmi/hooks/pools/types/index.ts @@ -1,9 +1,9 @@ -import { PublicWagmiConfig } from '@sushiswap/wagmi-config' -import { SushiSwapV2Pool } from 'sushi' import { ChainId } from 'sushi/chain' import { Type } from 'sushi/currency' import { TradeType } from 'sushi/dex' +import { SushiSwapV2Pool } from 'sushi/pool' import { UniV3Pool } from 'sushi/tines' +import { PublicWagmiConfig } from '../../../config/public' export enum PoolType { SushiSwapV2Pool = 'SushiSwapV2', diff --git a/apps/web/src/lib/wagmi/hooks/positions/actions/getConcentratedLiquidityPositionFees.ts b/apps/web/src/lib/wagmi/hooks/positions/actions/getConcentratedLiquidityPositionFees.ts index 6e2c21520b..d9b7b126f0 100644 --- a/apps/web/src/lib/wagmi/hooks/positions/actions/getConcentratedLiquidityPositionFees.ts +++ b/apps/web/src/lib/wagmi/hooks/positions/actions/getConcentratedLiquidityPositionFees.ts @@ -1,6 +1,6 @@ -import { PublicWagmiConfig } from '@sushiswap/wagmi-config' import { simulateContract } from '@wagmi/core/actions' import { SUSHISWAP_V3_POSTIION_MANAGER, SushiSwapV3ChainId } from 'sushi/config' +import { PublicWagmiConfig } from '../../../config/public' import { getConcentratedPositionOwners } from '../../pools/actions/getConcentratedPositionOwner' const MAX_UINT128 = 2n ** 128n - 1n diff --git a/apps/web/src/lib/wagmi/hooks/positions/actions/getConcentratedLiquidityPositions.ts b/apps/web/src/lib/wagmi/hooks/positions/actions/getConcentratedLiquidityPositions.ts index d41133c082..7d267d0675 100644 --- a/apps/web/src/lib/wagmi/hooks/positions/actions/getConcentratedLiquidityPositions.ts +++ b/apps/web/src/lib/wagmi/hooks/positions/actions/getConcentratedLiquidityPositions.ts @@ -1,3 +1,4 @@ +import { readContracts } from '@wagmi/core/actions' import { ChainId } from 'sushi/chain' import { SUSHISWAP_V3_FACTORY_ADDRESS, @@ -6,10 +7,8 @@ import { SushiSwapV3ChainId, } from 'sushi/config' import { computeSushiSwapV3PoolAddress } from 'sushi/pool/sushiswap-v3' - -import { PublicWagmiConfig } from '@sushiswap/wagmi-config' -import { readContracts } from '@wagmi/core/actions' import { erc20Abi } from 'viem' +import { PublicWagmiConfig } from '../../../config/public' import { ConcentratedLiquidityPosition } from '../types' import { getConcentratedLiquidityPositionFees } from './getConcentratedLiquidityPositionFees' import { getConcentratedLiquidityPositionsFromTokenIds } from './getConcentratedLiquidityPositionsFromTokenIds' diff --git a/apps/web/src/lib/wagmi/hooks/positions/actions/getConcentratedLiquidityPositionsFromTokenIds.ts b/apps/web/src/lib/wagmi/hooks/positions/actions/getConcentratedLiquidityPositionsFromTokenIds.ts index 4365db3e2a..1e562a545c 100644 --- a/apps/web/src/lib/wagmi/hooks/positions/actions/getConcentratedLiquidityPositionsFromTokenIds.ts +++ b/apps/web/src/lib/wagmi/hooks/positions/actions/getConcentratedLiquidityPositionsFromTokenIds.ts @@ -1,12 +1,11 @@ +import { readContracts } from '@wagmi/core/actions' import { SUSHISWAP_V3_FACTORY_ADDRESS, SUSHISWAP_V3_POSTIION_MANAGER, SushiSwapV3ChainId, } from 'sushi/config' import { computeSushiSwapV3PoolAddress } from 'sushi/pool/sushiswap-v3' - -import { PublicWagmiConfig } from '@sushiswap/wagmi-config' -import { readContracts } from '@wagmi/core/actions' +import { PublicWagmiConfig } from '../../../config/public' import { ConcentratedLiquidityPosition } from '../types' import { getConcentratedLiquidityPositionFees } from './getConcentratedLiquidityPositionFees' diff --git a/apps/web/src/lib/wagmi/hooks/tokens/useTokenWithCache.ts b/apps/web/src/lib/wagmi/hooks/tokens/useTokenWithCache.ts index 86afb390aa..c273428951 100644 --- a/apps/web/src/lib/wagmi/hooks/tokens/useTokenWithCache.ts +++ b/apps/web/src/lib/wagmi/hooks/tokens/useTokenWithCache.ts @@ -1,5 +1,4 @@ import { useCustomTokens } from '@sushiswap/hooks' -import { PublicWagmiConfig } from '@sushiswap/wagmi-config' import { keepPreviousData, useQuery } from '@tanstack/react-query' import { getToken as getTokenWeb3 } from '@wagmi/core/actions' import { useCallback } from 'react' @@ -7,6 +6,7 @@ import { ChainId } from 'sushi/chain' import { Token } from 'sushi/currency' import { Address, isAddress } from 'viem' import { useConfig } from 'wagmi' +import { PublicWagmiConfig } from '../../config/public' interface UseTokenParams { chainId: ChainId | undefined diff --git a/apps/web/src/lib/wagmi/index.ts b/apps/web/src/lib/wagmi/index.ts index 51272cd40a..29fe761a39 100644 --- a/apps/web/src/lib/wagmi/index.ts +++ b/apps/web/src/lib/wagmi/index.ts @@ -1,4 +1,4 @@ -import { PublicWagmiConfig } from '@sushiswap/wagmi-config' +import { PublicWagmiConfig } from './config/public' declare module 'wagmi' { interface Register { diff --git a/config/wagmi/README.md b/config/wagmi/README.md deleted file mode 100644 index 38a24b1f1e..0000000000 --- a/config/wagmi/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Wagmi Config - -... diff --git a/config/wagmi/package.json b/config/wagmi/package.json deleted file mode 100644 index c0ab3391e6..0000000000 --- a/config/wagmi/package.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "name": "@sushiswap/wagmi-config", - "version": "0.0.0", - "private": true, - "description": "Sushi Wagmi Config", - "keywords": [ - "sushi", - "wagmi", - "config" - ], - "homepage": "https://www.sushi.com", - "repository": { - "type": "git", - "url": "https://github.com/sushiswap/sushiswap.git", - "directory": "packages/config/wagmi" - }, - "license": "MIT", - "author": "LufyCZ ", - "sideEffects": false, - "type": "module", - "exports": { - ".": { - "types": "./dist/index.d.ts", - "default": "./dist/index.js" - }, - "./package.json": "./package.json" - }, - "main": "dist/index.js", - "source": "src/index.ts", - "types": "dist/index.d.ts", - "files": [ - "dist" - ], - "scripts": { - "build": "tsc", - "check": "tsc --pretty --noEmit", - "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist", - "dev": "tsc -w", - "prepublishOnly": "pnpm build", - "test": "jest --passWithNoTests" - }, - "jest": { - "preset": "@sushiswap/jest-config" - }, - "devDependencies": { - "@sushiswap/jest-config": "workspace:*", - "@tsconfig/esm": "1.0.4", - "@tsconfig/strictest": "2.0.2", - "@wagmi/core": "2.13.1", - "jest": "29.7.0", - "sushi": "workspace:*", - "typescript": "5.4.5" - }, - "peerDependencies": { - "@wagmi/core": "*", - "sushi": "*" - }, - "peerDependenciesMeta": { - "@wagmi/core": { - "optional": false - }, - "sushi": { - "optional": false - } - } -} diff --git a/config/wagmi/tsconfig.json b/config/wagmi/tsconfig.json deleted file mode 100644 index dc18cf12ae..0000000000 --- a/config/wagmi/tsconfig.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "extends": ["@tsconfig/strictest/tsconfig", "@tsconfig/esm/tsconfig"], - "include": ["src"], - "exclude": ["node_modules"], - "compilerOptions": { - "outDir": "./dist", - "rootDir": "./src", - "declaration": true, - "declarationMap": true, - "sourceMap": true - } -} diff --git a/jobs/pool/package.json b/jobs/pool/package.json index 523c903f02..1e0ff1aff6 100644 --- a/jobs/pool/package.json +++ b/jobs/pool/package.json @@ -36,7 +36,6 @@ "@sushiswap/database": "workspace:*", "@sushiswap/graph-client": "workspace:*", "@sushiswap/steer-sdk": "workspace:*", - "@sushiswap/wagmi-config": "workspace:*", "@wagmi/core": "2.13.1", "@whatwg-node/fetch": "0.8.4", "connect-timeout": "1.9.0", diff --git a/jobs/pool/src/lib/wagmi.ts b/jobs/pool/src/lib/wagmi.ts index c333647cdc..81cc731f00 100644 --- a/jobs/pool/src/lib/wagmi.ts +++ b/jobs/pool/src/lib/wagmi.ts @@ -1,6 +1,12 @@ -import { publicWagmiConfig } from '@sushiswap/wagmi-config' import { createConfig } from '@wagmi/core' +import { publicChains, publicTransports } from 'sushi/config' export const config = createConfig({ - ...publicWagmiConfig, -}) + chains: publicChains, + transports: publicTransports, + batch: { + multicall: { + wait: 64, + }, + }, +} as const satisfies Parameters[0]) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5f2fae14b6..9d5f5e32b9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -218,9 +218,6 @@ importers: '@sushiswap/default-token-list': specifier: ^43.1.0 version: 43.3.0 - '@sushiswap/wagmi-config': - specifier: workspace:* - version: link:../../config/wagmi '@upstash/redis': specifier: 1.22.1 version: 1.22.1 @@ -599,9 +596,6 @@ importers: '@sushiswap/ui': specifier: workspace:* version: link:../../packages/ui - '@sushiswap/wagmi-config': - specifier: workspace:* - version: link:../../config/wagmi '@tanstack/react-query': specifier: 5.51.16 version: 5.51.16(react@18.2.0) @@ -955,30 +949,6 @@ importers: config/typescript: {} - config/wagmi: - devDependencies: - '@sushiswap/jest-config': - specifier: workspace:* - version: link:../jest - '@tsconfig/esm': - specifier: 1.0.4 - version: 1.0.4 - '@tsconfig/strictest': - specifier: 2.0.2 - version: 2.0.2 - '@wagmi/core': - specifier: 2.13.1 - version: 2.13.1(@tanstack/query-core@5.51.16)(@types/react@18.2.14)(immer@9.0.21)(react@18.2.0)(typescript@5.4.5)(viem@2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@6.0.3)(zod@3.23.8)) - jest: - specifier: 29.7.0 - version: 29.7.0(@types/node@22.1.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5)) - sushi: - specifier: workspace:* - version: link:../../packages/sushi - typescript: - specifier: 5.4.5 - version: 5.4.5 - jobs/pool: dependencies: '@ethersproject/address': @@ -1002,9 +972,6 @@ importers: '@sushiswap/steer-sdk': specifier: workspace:* version: link:../../packages/steer-sdk - '@sushiswap/wagmi-config': - specifier: workspace:* - version: link:../../config/wagmi '@wagmi/core': specifier: 2.13.1 version: 2.13.1(@tanstack/query-core@5.51.16)(@types/react@18.2.14)(immer@9.0.21)(react@18.2.0)(typescript@5.4.5)(viem@2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@6.0.3)(zod@3.23.8)) @@ -1084,7 +1051,7 @@ importers: optionalDependencies: next: specifier: 14.2.3 - version: 14.2.3(@babel/core@7.24.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.45.0)(babel-plugin-macros@3.1.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + version: 14.2.3(@babel/core@7.23.2)(@opentelemetry/api@1.9.0)(@playwright/test@1.45.0)(babel-plugin-macros@3.1.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) devDependencies: '@sushiswap/jest-config': specifier: workspace:* @@ -1106,7 +1073,7 @@ importers: version: 29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5)) ts-jest: specifier: 29.1.1 - version: 29.1.1(@babel/core@7.24.4)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.4))(jest@29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5)))(typescript@5.4.5) + version: 29.1.1(@babel/core@7.23.2)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.2))(jest@29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5)))(typescript@5.4.5) typescript: specifier: 5.4.5 version: 5.4.5 @@ -1348,7 +1315,7 @@ importers: version: 18.2.6 jest: specifier: 29.7.0 - version: 29.7.0(@types/node@22.1.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5)) + version: 29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5)) react: specifier: 18.2.0 version: 18.2.0 @@ -1360,7 +1327,7 @@ importers: version: link:../sushi tailwindcss: specifier: 3.3.2 - version: 3.3.2(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5)) + version: 3.3.2(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5)) typescript: specifier: 5.4.5 version: 5.4.5 @@ -1461,7 +1428,7 @@ importers: version: 18.2.6 jest: specifier: 29.7.0 - version: 29.7.0(@types/node@22.1.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5)) + version: 29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5)) next: specifier: 14.2.3 version: 14.2.3(@babel/core@7.24.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.45.0)(babel-plugin-macros@3.1.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) @@ -27048,41 +27015,6 @@ snapshots: - supports-color - ts-node - '@jest/core@29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5))': - dependencies: - '@jest/console': 29.7.0 - '@jest/reporters': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 22.1.0 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - ci-info: 3.8.0 - exit: 0.1.2 - graceful-fs: 4.2.11 - jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@22.1.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5)) - jest-haste-map: 29.7.0 - jest-message-util: 29.7.0 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-resolve-dependencies: 29.7.0 - jest-runner: 29.7.0 - jest-runtime: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 - jest-validate: 29.7.0 - jest-watcher: 29.7.0 - micromatch: 4.0.5 - pretty-format: 29.7.0 - slash: 3.0.0 - strip-ansi: 6.0.1 - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - - ts-node - '@jest/create-cache-key-function@29.7.0': dependencies: '@jest/types': 29.6.3 @@ -36058,6 +35990,20 @@ snapshots: transitivePeerDependencies: - supports-color + babel-jest@29.7.0(@babel/core@7.23.2): + dependencies: + '@babel/core': 7.23.2 + '@jest/transform': 29.7.0 + '@types/babel__core': 7.20.1 + babel-plugin-istanbul: 6.1.1 + babel-preset-jest: 29.6.3(@babel/core@7.23.2) + chalk: 4.1.2 + graceful-fs: 4.2.11 + slash: 3.0.0 + transitivePeerDependencies: + - supports-color + optional: true + babel-jest@29.7.0(@babel/core@7.24.4): dependencies: '@babel/core': 7.24.4 @@ -36449,6 +36395,13 @@ snapshots: babel-plugin-jest-hoist: 29.6.3 babel-preset-current-node-syntax: 1.0.1(@babel/core@7.22.10) + babel-preset-jest@29.6.3(@babel/core@7.23.2): + dependencies: + '@babel/core': 7.23.2 + babel-plugin-jest-hoist: 29.6.3 + babel-preset-current-node-syntax: 1.0.1(@babel/core@7.23.2) + optional: true + babel-preset-jest@29.6.3(@babel/core@7.24.4): dependencies: '@babel/core': 7.24.4 @@ -37739,21 +37692,6 @@ snapshots: - supports-color - ts-node - create-jest@29.7.0(@types/node@22.1.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5)): - dependencies: - '@jest/types': 29.6.3 - chalk: 4.1.2 - exit: 0.1.2 - graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@22.1.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5)) - jest-util: 29.7.0 - prompts: 2.4.2 - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - create-require@1.1.1: {} cross-argv@2.0.0: {} @@ -42934,25 +42872,6 @@ snapshots: - supports-color - ts-node - jest-cli@29.7.0(@types/node@22.1.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5)): - dependencies: - '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5)) - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 - chalk: 4.1.2 - create-jest: 29.7.0(@types/node@22.1.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5)) - exit: 0.1.2 - import-local: 3.1.0 - jest-config: 29.7.0(@types/node@22.1.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5)) - jest-util: 29.7.0 - jest-validate: 29.7.0 - yargs: 17.7.2 - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - jest-config@27.5.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5))(utf-8-validate@5.0.10): dependencies: '@babel/core': 7.24.4 @@ -43111,37 +43030,6 @@ snapshots: - babel-plugin-macros - supports-color - jest-config@29.7.0(@types/node@22.1.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5)): - dependencies: - '@babel/core': 7.22.10 - '@jest/test-sequencer': 29.7.0 - '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.22.10) - chalk: 4.1.2 - ci-info: 3.8.0 - deepmerge: 4.3.1 - glob: 7.2.3 - graceful-fs: 4.2.11 - jest-circus: 29.7.0(babel-plugin-macros@3.1.0) - jest-environment-node: 29.7.0 - jest-get-type: 29.6.3 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-runner: 29.7.0 - jest-util: 29.7.0 - jest-validate: 29.7.0 - micromatch: 4.0.5 - parse-json: 5.2.0 - pretty-format: 29.7.0 - slash: 3.0.0 - strip-json-comments: 3.1.1 - optionalDependencies: - '@types/node': 22.1.0 - ts-node: 10.9.2(@types/node@22.1.0)(typescript@5.4.5) - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - jest-diff@27.5.1: dependencies: chalk: 4.1.2 @@ -43727,18 +43615,6 @@ snapshots: - supports-color - ts-node - jest@29.7.0(@types/node@22.1.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5)): - dependencies: - '@jest/core': 29.7.0(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5)) - '@jest/types': 29.6.3 - import-local: 3.1.0 - jest-cli: 29.7.0(@types/node@22.1.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.1.0)(typescript@5.4.5)) - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - jiti@1.19.1: {} jiti@1.21.0: {} @@ -45700,6 +45576,34 @@ snapshots: next-tick@1.1.0: {} + next@14.2.3(@babel/core@7.23.2)(@opentelemetry/api@1.9.0)(@playwright/test@1.45.0)(babel-plugin-macros@3.1.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + dependencies: + '@next/env': 14.2.3 + '@swc/helpers': 0.5.5 + busboy: 1.6.0 + caniuse-lite: 1.0.30001611 + graceful-fs: 4.2.11 + postcss: 8.4.31 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + styled-jsx: 5.1.1(@babel/core@7.23.2)(babel-plugin-macros@3.1.0)(react@18.2.0) + optionalDependencies: + '@next/swc-darwin-arm64': 14.2.3 + '@next/swc-darwin-x64': 14.2.3 + '@next/swc-linux-arm64-gnu': 14.2.3 + '@next/swc-linux-arm64-musl': 14.2.3 + '@next/swc-linux-x64-gnu': 14.2.3 + '@next/swc-linux-x64-musl': 14.2.3 + '@next/swc-win32-arm64-msvc': 14.2.3 + '@next/swc-win32-ia32-msvc': 14.2.3 + '@next/swc-win32-x64-msvc': 14.2.3 + '@opentelemetry/api': 1.9.0 + '@playwright/test': 1.45.0 + transitivePeerDependencies: + - '@babel/core' + - babel-plugin-macros + optional: true + next@14.2.3(@babel/core@7.24.4)(@opentelemetry/api@1.9.0)(@playwright/test@1.45.0)(babel-plugin-macros@3.1.0)(react-dom@18.2.0(react@18.2.0))(react@18.2.0): dependencies: '@next/env': 14.2.3 @@ -49896,6 +49800,15 @@ snapshots: dependencies: webpack: 5.91.0 + styled-jsx@5.1.1(@babel/core@7.23.2)(babel-plugin-macros@3.1.0)(react@18.2.0): + dependencies: + client-only: 0.0.1 + react: 18.2.0 + optionalDependencies: + '@babel/core': 7.23.2 + babel-plugin-macros: 3.1.0 + optional: true + styled-jsx@5.1.1(@babel/core@7.24.4)(babel-plugin-macros@3.1.0)(react@18.2.0): dependencies: client-only: 0.0.1 @@ -50618,7 +50531,7 @@ snapshots: ts-interface-checker@0.1.13: {} - ts-jest@29.1.1(@babel/core@7.24.4)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.4))(jest@29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5)))(typescript@5.4.5): + ts-jest@29.1.1(@babel/core@7.23.2)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.2))(jest@29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5)))(typescript@5.4.5): dependencies: bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 @@ -50631,9 +50544,9 @@ snapshots: typescript: 5.4.5 yargs-parser: 21.1.1 optionalDependencies: - '@babel/core': 7.24.4 + '@babel/core': 7.23.2 '@jest/types': 29.6.3 - babel-jest: 29.7.0(@babel/core@7.24.4) + babel-jest: 29.7.0(@babel/core@7.23.2) ts-jest@29.1.1(@babel/core@7.24.4)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.4))(jest@29.7.0(@types/node@20.14.14)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.5.4)))(typescript@5.5.4): dependencies: From 7b966c63e5f8a06ce273d5e3b46a58f766cf71eb Mon Sep 17 00:00:00 2001 From: Matthew Lilley Date: Sat, 10 Aug 2024 16:42:12 +0100 Subject: [PATCH 124/125] chore: ignore check on pool job --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 16e976f096..6f0078e707 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "changeset": "changeset", "changeset:publish": "changeset publish", "changeset:version": "changeset version && pnpm install --lockfile-only", - "check": "turbo run check --no-cache --filter=!@sushiswap/tines-sandbox --filter=!@sushiswap/route-processor", + "check": "turbo run check --no-cache --filter=!@sushiswap/pool-job --filter=!@sushiswap/tines-sandbox --filter=!@sushiswap/route-processor", "clean": "turbo run clean && rm -rf node_modules", "dev": "dotenv -- turbo run dev --no-cache --parallel --continue", "disable-remote-caching": "turbo unlink && rm -rf ./node_modules/.cache/turbo", From 39b6f4353bca810653232bad2e526094584e6bb3 Mon Sep 17 00:00:00 2001 From: denis-orbs Date: Mon, 12 Aug 2024 17:09:18 +0300 Subject: [PATCH 125/125] dTWAP and dLIMIT by Orbs --- apps/web/package.json | 1 + apps/web/src/app/(evm)/swap/limit/loading.tsx | 6 + apps/web/src/app/(evm)/swap/limit/page.tsx | 18 + apps/web/src/app/(evm)/swap/twap/loading.tsx | 7 + apps/web/src/app/(evm)/swap/twap/page.tsx | 21 + apps/web/src/ui/swap/swap-mode-buttons.tsx | 10 + apps/web/src/ui/swap/twap/twap.tsx | 267 +++++++++++ config/nextjs/index.js | 1 + pnpm-lock.yaml | 431 +++++++++++------- 9 files changed, 603 insertions(+), 159 deletions(-) create mode 100644 apps/web/src/app/(evm)/swap/limit/loading.tsx create mode 100644 apps/web/src/app/(evm)/swap/limit/page.tsx create mode 100644 apps/web/src/app/(evm)/swap/twap/loading.tsx create mode 100644 apps/web/src/app/(evm)/swap/twap/page.tsx create mode 100644 apps/web/src/ui/swap/twap/twap.tsx diff --git a/apps/web/package.json b/apps/web/package.json index 2c7afb5cc5..b1303e34fb 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -33,6 +33,7 @@ "@next/bundle-analyzer": "^14.2.3", "@octokit/auth-app": "4.0.7", "@pontem/wallet-adapter-plugin": "^0.2.1", + "@orbs-network/twap-ui-sushiswap": "1.1.21", "@radix-ui/react-slot": "1.0.2", "@rainbow-me/rainbowkit": "2.1.3", "@rise-wallet/wallet-adapter": "^0.1.2", diff --git a/apps/web/src/app/(evm)/swap/limit/loading.tsx b/apps/web/src/app/(evm)/swap/limit/loading.tsx new file mode 100644 index 0000000000..121536def8 --- /dev/null +++ b/apps/web/src/app/(evm)/swap/limit/loading.tsx @@ -0,0 +1,6 @@ +import React from "react"; +import SimpleSwapLoading from "../(simple)/loading"; + +export default function Loader() { + return ; +} diff --git a/apps/web/src/app/(evm)/swap/limit/page.tsx b/apps/web/src/app/(evm)/swap/limit/page.tsx new file mode 100644 index 0000000000..d21d04b117 --- /dev/null +++ b/apps/web/src/app/(evm)/swap/limit/page.tsx @@ -0,0 +1,18 @@ +import { Container } from '@sushiswap/ui' +import dynamic from 'next/dynamic' +import { Providers } from '../(simple)/providers' +const LimitPanel = dynamic(() => import('src/ui/swap/twap/twap').then(it => it.LimitPanel), {ssr: false}) + +export const metadata = { + title: 'SushiSwap', +} + +export default function SwapLimitPage() { + return ( + + + + + + ) +} diff --git a/apps/web/src/app/(evm)/swap/twap/loading.tsx b/apps/web/src/app/(evm)/swap/twap/loading.tsx new file mode 100644 index 0000000000..fb5ab4014d --- /dev/null +++ b/apps/web/src/app/(evm)/swap/twap/loading.tsx @@ -0,0 +1,7 @@ +import React from "react"; +import SimpleSwapLoading from "../(simple)/loading"; + +export default function Loader() { + return ; + +} diff --git a/apps/web/src/app/(evm)/swap/twap/page.tsx b/apps/web/src/app/(evm)/swap/twap/page.tsx new file mode 100644 index 0000000000..1a8addf736 --- /dev/null +++ b/apps/web/src/app/(evm)/swap/twap/page.tsx @@ -0,0 +1,21 @@ +import { Container } from '@sushiswap/ui' +import { Providers } from '../(simple)/providers' +import dynamic from 'next/dynamic' + + +const TWAPPanel = dynamic(() => import('src/ui/swap/twap/twap').then(it => it.TWAPPanel), {ssr: false}) + +export const metadata = { + title: 'SushiSwap', +} + +export default function SwapTwapPage() { + return ( + + + + + + ) + } + \ No newline at end of file diff --git a/apps/web/src/ui/swap/swap-mode-buttons.tsx b/apps/web/src/ui/swap/swap-mode-buttons.tsx index 34142aa79c..f6df857634 100644 --- a/apps/web/src/ui/swap/swap-mode-buttons.tsx +++ b/apps/web/src/ui/swap/swap-mode-buttons.tsx @@ -22,6 +22,16 @@ export const SwapModeButtons = () => { Swap + + + Limit + + + + + TWAP + + diff --git a/apps/web/src/ui/swap/twap/twap.tsx b/apps/web/src/ui/swap/twap/twap.tsx new file mode 100644 index 0000000000..38fbc93247 --- /dev/null +++ b/apps/web/src/ui/swap/twap/twap.tsx @@ -0,0 +1,267 @@ +"use client"; + +import { + TWAP as TwapContainer, + supportedChains, +} from "@orbs-network/twap-ui-sushiswap"; +import { useConnectModal } from "@rainbow-me/rainbowkit"; +import { useAccount, useChainId, useSwitchChain} from "wagmi"; +import { ChainId } from 'sushi/chain' +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + Tooltip as SushiTooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, + NetworkSelector, + Button +} from "@sushiswap/ui"; +import { + ExclamationCircleIcon, +} from '@heroicons/react/20/solid' +import { Currency } from "sushi/currency"; +import { ReactNode, useCallback, useEffect, useMemo } from "react"; +import { useSortedTokenList } from "src/lib/wagmi/components/token-selector/hooks/useSortedTokenList"; +import { useCustomTokens } from "@sushiswap/hooks"; +import { + useOtherTokenListsQuery, + usePrice, + useTokens, +} from "@sushiswap/react-query"; +import { useTheme } from "next-themes"; + +import { Address } from "viem"; +import { TokenSelector } from "src/lib/wagmi/components/token-selector/TokenSelector"; +import { SimpleSwapHeader } from "../simple/simple-swap-header"; +import { SimpleSwapBridgeBanner } from "../simple/simple-swap-bridge-banner"; +import { SwapModeButtons } from "../swap-mode-buttons"; +import { SimpleSwapSettingsOverlay } from "../simple/simple-swap-settings-overlay"; +import { useDerivedStateSimpleSwap, useSimpleSwapTrade } from "../simple/derivedstate-simple-swap-provider"; + + +const Modal = ({ + open, + onClose, + title, + children, + header, +}: { + open: boolean; + onClose: () => void; + title?: string; + children?: ReactNode; + header?: ReactNode; +}) => { + return ( + + + + {header} + {title && {title}} + + {children} + + + ); +}; + +const TokenSelectModal = ({ + selected, + children, + onSelect, +}: { + selected: Currency; + children: ReactNode; + onSelect: (currency: Currency) => void; +}) => { + const { state: { chainId } } = useDerivedStateSimpleSwap() + + return ( + + {children} + + ); +}; + + +const useTrade = () => { + const { data: trade, isInitialLoading } = useSimpleSwapTrade(); + + return { + isLoading: isInitialLoading, + outAmount: trade?.amountOut?.quotient.toString() + }; +}; + +const usePriceUSD = (address?: Address) => { + const { state: { chainId } } = useDerivedStateSimpleSwap() + + const { data: price } = usePrice({ + chainId, + enabled: true, + address, + }); + + return price?.toSignificant(6); +}; + +const getTokenLogo = (currency: Currency) => { + try { + const src = currency.isNative + ? `native-currency/ethereum.svg` + : `tokens/${currency.chainId}/${currency.wrapped.address}.jpg`; + const params = ["f_auto", "c_limit", `w_${64}`]; + return `https://cdn.sushi.com/image/upload/${params.join( + "," + )}/d_unknown.png/${src}`; + } catch (error) { + return ""; + } +}; + +const useTokenList = () => { + const { data: customTokenMap } = useCustomTokens(); + const { state: { chainId } } = useDerivedStateSimpleSwap() + + const { data: otherTokenMap } = useOtherTokenListsQuery({ + chainId, + query: undefined, + }); + const { data: defaultTokenMap } = useTokens({ + chainId, + }); + + const tokenMap = useMemo(() => { + return { + ...defaultTokenMap, + ...otherTokenMap, + }; + }, [defaultTokenMap, otherTokenMap]); + + const { data: sortedTokenList } = useSortedTokenList({ + query: "", + customTokenMap, + tokenMap, + chainId, + includeNative: true, + }); + + return sortedTokenList; +}; + +const Tooltip = ({tooltipText}:any) => { + return + + + + + +

    {tooltipText}

    +
    +
    +
    +} + + + +const TwapNetworkSelector = ({children}:{children: ReactNode}) => { + const { switchChain } = useSwitchChain() +const chainId = useChainId() + const onSelect = useCallback( + (chainId: number) => { + switchChain({chainId: chainId as ChainId}) + }, + [switchChain], + ) + + + return + {children} + +} + + +const TwapButton = ({disabled, children}:{disabled?: boolean, children: ReactNode}) => { + + return +} + +function Provider({ isLimit }: { isLimit?: boolean }) { + const { openConnectModal } = useConnectModal(); + const { connector } = useAccount(); + const { state, mutate } = useDerivedStateSimpleSwap(); + const { resolvedTheme } = useTheme(); + const tokens = useTokenList(); + const connectedChainId = useChainId() + + useEffect(() => { + // we do this to get an indication of market price for single token + if (state.swapAmountString !== "1") { + mutate.setSwapAmount("1"); + } + }, [state.swapAmountString]); + + return ( +
    + + +
    + + +
    + + +
    + ); +} +export const LimitPanel = () => { + return ; +}; + +export const TWAPPanel = () => { + return ; +}; diff --git a/config/nextjs/index.js b/config/nextjs/index.js index ec086789cd..3b3c2471ae 100644 --- a/config/nextjs/index.js +++ b/config/nextjs/index.js @@ -47,6 +47,7 @@ const defaultNextConfig = { config.plugins.push( new webpack.IgnorePlugin({ resourceRegExp: /^(lokijs|pino-pretty|encoding)$/, + resourceRegExp: /^(lokijs|pino-pretty|encoding|keyv)$/, }), ) } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9d5f5e32b9..1db0d06114 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -146,7 +146,7 @@ importers: version: 2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8) wagmi: specifier: 2.12.2 - version: 2.12.2(@tanstack/query-core@5.51.16)(@tanstack/react-query@5.51.16(react@18.2.0))(@types/react@18.2.14)(bufferutil@4.0.8)(immer@9.0.21)(react@18.2.0)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8) + version: 2.12.2(@tanstack/query-core@5.51.16)(@tanstack/react-query@5.51.16(react@18.2.0))(@types/react@18.2.14)(bufferutil@4.0.8)(immer@9.0.21)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8) zod: specifier: 3.23.8 version: 3.23.8 @@ -542,6 +542,9 @@ importers: '@octokit/auth-app': specifier: 4.0.7 version: 4.0.7(encoding@0.1.13) + '@orbs-network/twap-ui-sushiswap': + specifier: 1.1.21 + version: 1.1.21(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react-native@0.73.7(@babel/core@7.24.4)(@babel/preset-env@7.24.4(@babel/core@7.24.4))(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(utf-8-validate@5.0.10))(react@18.2.0)(utf-8-validate@5.0.10) '@pontem/wallet-adapter-plugin': specifier: ^0.2.1 version: 0.2.1 @@ -1137,7 +1140,7 @@ importers: version: 2.1.5(react@18.2.0) tsup: specifier: 7.2.0 - version: 7.2.0(@swc/core@1.4.2)(postcss@8.4.31)(ts-node@10.9.2(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5) + version: 7.2.0(@swc/core@1.4.2)(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5) typescript: specifier: 5.4.5 version: 5.4.5 @@ -1455,7 +1458,7 @@ importers: dependencies: '@steerprotocol/contracts': specifier: 2.1.0-beta.14 - version: 2.1.0-beta.14(bufferutil@4.0.8)(encoding@0.1.13)(squirrelly@8.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) + version: 2.1.0-beta.14(bufferutil@4.0.8)(squirrelly@8.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10) '@sushiswap/database': specifier: workspace:* version: link:../database @@ -1470,7 +1473,7 @@ importers: version: 2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8) wagmi: specifier: 2.12.2 - version: 2.12.2(@tanstack/query-core@5.51.16)(@tanstack/react-query@5.51.16(react@18.2.0))(@types/react@18.2.14)(bufferutil@4.0.8)(encoding@0.1.13)(immer@9.0.21)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8) + version: 2.12.2(@tanstack/query-core@5.51.16)(@tanstack/react-query@5.51.16(react@18.2.0))(@types/react@18.2.14)(bufferutil@4.0.8)(immer@9.0.21)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8) optionalDependencies: next: specifier: 14.2.3 @@ -1556,6 +1559,10 @@ importers: specifier: 3.23.8 version: 3.23.8 + packages/sushi/dist/_cjs: {} + + packages/sushi/dist/_esm: {} + packages/telemetry: devDependencies: '@tsconfig/esm': @@ -2050,7 +2057,7 @@ importers: version: 10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5) tsup: specifier: 7.2.0 - version: 7.2.0(@swc/core@1.4.2)(postcss@8.4.31)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5) + version: 7.2.0(@swc/core@1.4.2)(postcss@8.4.38)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5) typescript: specifier: 5.4.5 version: 5.4.5 @@ -3933,6 +3940,9 @@ packages: resolution: {integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==} engines: {node: '>=10'} + '@defi.org/web3-candies@5.0.0': + resolution: {integrity: sha512-I5CZ2rESrDo9rV63yrSVS1ILbkCTSC5AeR9rmPtE+ovmOcrPFRcf2xKlPSjKU2FE3vzzb7kB/IEbRACW85C9zg==} + '@dependents/detective-less@4.1.0': resolution: {integrity: sha512-KrkT6qO5NxqNfy68sBl6CTSoJ4SNDIS5iQArkibhlbGU4LaDukZ3q2HIkh8aUKDio6o4itU4xDR7t82Y2eP1Bg==} engines: {node: '>=14'} @@ -4035,12 +4045,21 @@ packages: '@emotion/is-prop-valid@0.8.8': resolution: {integrity: sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==} + '@emotion/is-prop-valid@1.2.2': + resolution: {integrity: sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==} + '@emotion/memoize@0.7.4': resolution: {integrity: sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==} + '@emotion/memoize@0.8.1': + resolution: {integrity: sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==} + '@emotion/unitless@0.7.5': resolution: {integrity: sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==} + '@emotion/unitless@0.8.1': + resolution: {integrity: sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==} + '@emotion/use-insertion-effect-with-fallbacks@1.0.1': resolution: {integrity: sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==} peerDependencies: @@ -6028,6 +6047,21 @@ packages: '@openzeppelin/contracts@4.9.3': resolution: {integrity: sha512-He3LieZ1pP2TNt5JbkPA4PNT9WC3gOTOlDcFGJW4Le4QKqwmiNJCRt44APfxMxvq7OugU/cqYuPcSBzOw38DAg==} + '@orbs-network/twap-ui-sushiswap@1.1.21': + resolution: {integrity: sha512-cUopb8OZEMxM+doyNOKr77ZLAVUFAuq6R8tSoF9pJQCOZf3uSULWS3KFJtDlaZdisQBwBOkJFozh8orY6HiyeQ==} + peerDependencies: + react: '*' + react-dom: '*' + + '@orbs-network/twap-ui@1.1.21': + resolution: {integrity: sha512-l1aDCg6axMBx08hEVf1hQs2r+LuIdGv7/V1EBcGqPfH8/CVnd7RiNO+fAKR//2fnXPL0plpLN3IAUldVTGeMzA==} + peerDependencies: + react: '*' + react-dom: '*' + + '@orbs-network/twap@2.2.1': + resolution: {integrity: sha512-SN6L7mDZOFcJpeklcVrzkimNsyosjfXoooPORmZM+h8WTOpK0hnV25DndKmAX1PG3SwLq2LdtMdFBvkUKWDQ6w==} + '@pancakeswap/v3-core@1.0.2': resolution: {integrity: sha512-9aZU8I1J6SbZOSW7NcNxuyaAC17tGkOaZJM9aJgvl6MMUOExpq0i0EC/jc3HxWbpC8sbZL+8eG544NEJs8CS+w==} engines: {node: '>=10'} @@ -6966,6 +7000,11 @@ packages: peerDependencies: react: '>=16.8' + '@react-icons/all-files@4.1.0': + resolution: {integrity: sha512-hxBI2UOuVaI3O/BhQfhtb4kcGn9ft12RWAFVMUeNjqqhLsHvFtzIkFaptBJpFDANTKoDfdVoHTKZDlwKCACbMQ==} + peerDependencies: + react: '*' + '@react-native-community/cli-clean@12.3.6': resolution: {integrity: sha512-gUU29ep8xM0BbnZjwz9MyID74KKwutq9x5iv4BCr2im6nly4UMf1B1D+V225wR7VcDGzbgWjaezsJShLLhC5ig==} @@ -8382,6 +8421,9 @@ packages: '@tanstack/query-core@4.27.0': resolution: {integrity: sha512-sm+QncWaPmM73IPwFlmWSKPqjdTXZeFf/7aEmWh00z7yl2FjqophPt0dE1EHW9P1giMC5rMviv7OUbSDmWzXXA==} + '@tanstack/query-core@4.36.1': + resolution: {integrity: sha512-DJSilV5+ytBP1FbFcEJovv4rnnm/CokuVvrBEtW/Va9DvuJ3HksbXUJEpI0aV1KtuL4ZoO9AVE6PyNLzF7tLeA==} + '@tanstack/query-core@5.51.16': resolution: {integrity: sha512-zfV+WAtBGm1dUIbL0w/x8qTqVLKU1/Bo1p19J9LF02MmIc4FxzMImMXhFzYJQl5Hx8Wit6RiQ4tB/DvN8y9zaQ==} @@ -8400,6 +8442,18 @@ packages: peerDependencies: '@tanstack/react-query': 4.28.0 + '@tanstack/react-query@4.36.1': + resolution: {integrity: sha512-y7ySVHFyyQblPl3J3eQBWpXZkliroki3ARnBKsdJchlgt7yJLRDUcf4B8soufgiYt3pEQIkBWBx1N9/ZPIeUWw==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-native: '*' + peerDependenciesMeta: + react-dom: + optional: true + react-native: + optional: true + '@tanstack/react-query@5.51.16': resolution: {integrity: sha512-NZnpJ30zkwaA2ZPhxJLs/qoMbd0yNAj6yyb3JTADJx9HjSdtvnNzOY1bDa3bU1B9CZTBBb7W9E1PpWlNXdgESg==} peerDependencies: @@ -9066,6 +9120,9 @@ packages: '@types/stack-utils@2.0.1': resolution: {integrity: sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==} + '@types/stylis@4.2.5': + resolution: {integrity: sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw==} + '@types/supports-color@8.1.1': resolution: {integrity: sha512-dPWnWsf+kzIG140B8z2w3fr5D03TLWbOAFQl45xUpI3vcizeXriNR5VYkWZ+WTMsUHqZ9Xlt3hrxGNANFyNQfw==} @@ -10990,6 +11047,9 @@ packages: resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==} engines: {node: '>=14.16'} + camelize@1.0.1: + resolution: {integrity: sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==} + caniuse-api@3.0.0: resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} @@ -11668,6 +11728,10 @@ packages: peerDependencies: postcss: ^8.4 + css-color-keywords@1.0.0: + resolution: {integrity: sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==} + engines: {node: '>=4'} + css-declaration-sorter@6.4.1: resolution: {integrity: sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==} engines: {node: ^10 || ^12 || >=14} @@ -11728,6 +11792,9 @@ packages: css-select@5.1.0: resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==} + css-to-react-native@3.2.0: + resolution: {integrity: sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==} + css-tree@1.0.0-alpha.37: resolution: {integrity: sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==} engines: {node: '>=8.0.0'} @@ -17062,6 +17129,11 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + nanoid@3.3.7: + resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + nanoid@4.0.0: resolution: {integrity: sha512-IgBP8piMxe/gf73RTQx7hmnhwz0aaEXYakvqZyE302IXW3HyVNhdNGC+O2MwMAVhLEnvXlvKtGbtJf6wvHihCg==} engines: {node: ^14 || ^16 || >=18} @@ -18374,6 +18446,10 @@ packages: resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} engines: {node: ^10 || ^12 || >=14} + postcss@8.4.38: + resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} + engines: {node: ^10 || ^12 || >=14} + postgres-array@2.0.0: resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==} engines: {node: '>=4'} @@ -19047,6 +19123,11 @@ packages: react: ^0.14.8 || ^15.0.1 || ^16.0.0 || ^17.0.1 || ^18.0.0 react-dom: ^0.14.8 || ^15.0.1 || ^16.0.0 || ^17.0.1 || ^18.0.0 + react-error-boundary@4.0.13: + resolution: {integrity: sha512-b6PwbdSv8XeOSYvjt8LpgpKrZ0yGdtZokYwkwV2wlcZbxgopHX/hgPl5VgpnoVOWd868n1hktM8Qm4b+02MiLQ==} + peerDependencies: + react: '>=16.13.1' + react-error-overlay@6.0.11: resolution: {integrity: sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==} @@ -19107,6 +19188,12 @@ packages: peerDependencies: react: 18.2.0 + react-number-format@5.4.0: + resolution: {integrity: sha512-NWdICrqLhI7rAS8yUeLVd6Wr4cN7UjJ9IBTS0f/a9i7UB4x4Ti70kGnksBtZ7o4Z7YRbvCMMR/jQmkoOBa/4fg==} + peerDependencies: + react: ^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 + react-dom: ^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 + react-onclickoutside@6.13.0: resolution: {integrity: sha512-ty8So6tcUpIb+ZE+1HAhbLROvAIJYyJe/1vRrrcmW+jLsaM+/powDRqxzo6hSh9CuRZGSL1Q8mvcF5WRD93a0A==} peerDependencies: @@ -19242,6 +19329,12 @@ packages: react: '>=16.13' react-dom: '>=16.13' + react-virtualized-auto-sizer@1.0.24: + resolution: {integrity: sha512-3kCn7N9NEb3FlvJrSHWGQ4iVl+ydQObq2fHMn12i5wbtm74zHOPhz/i64OL3c1S1vi9i2GXtZqNqUJTQ+BnNfg==} + peerDependencies: + react: ^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0 + react-dom: ^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0 + react-virtualized-auto-sizer@1.0.7: resolution: {integrity: sha512-Mxi6lwOmjwIjC1X4gABXMJcKHsOo0xWl3E3ugOgufB8GJU+MqrtY35aBuvCYv/razQ1Vbp7h1gWJjGjoNN5pmA==} engines: {node: '>8.0.0'} @@ -19249,6 +19342,13 @@ packages: react: ^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0-rc react-dom: ^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0-rc + react-window@1.8.10: + resolution: {integrity: sha512-Y0Cx+dnU6NLa5/EvoHukUD0BklJ8qITCtVEPY1C/nL8wwoZ0b5aEw8Ff1dOVHw7fCzMt55XfJDd8S8W8LCaUCg==} + engines: {node: '>8.0.0'} + peerDependencies: + react: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 + react-dom: ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 + react-window@1.8.7: resolution: {integrity: sha512-JHEZbPXBpKMmoNO1bNhoXOOLg/ujhL/BU4IqVU9r8eQPcy5KQnGHIHDRkJ0ns9IM5+Aq5LNwt3j8t3tIrePQzA==} engines: {node: '>8.0.0'} @@ -20050,6 +20150,9 @@ packages: shallow-equal@1.2.1: resolution: {integrity: sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==} + shallowequal@1.1.0: + resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==} + sharp@0.32.6: resolution: {integrity: sha512-KyLTWwgcR9Oe4d9HwCwNM2l7+J0dUQwn/yf7S0EnTtb0eVS4RxO0eUSvxPtzT4F3SY+C4K6fqdv/DO27sJ/v/w==} engines: {node: '>=14.15.0'} @@ -20618,6 +20721,13 @@ packages: peerDependencies: webpack: ^5.0.0 + styled-components@6.1.12: + resolution: {integrity: sha512-n/O4PzRPhbYI0k1vKKayfti3C/IGcPf+DqcrOB7O/ab9x4u/zjqraneT5N45+sIe87cxrCApXM8Bna7NYxwoTA==} + engines: {node: '>= 16'} + peerDependencies: + react: '>= 16.8.0' + react-dom: '>= 16.8.0' + styled-jsx@5.1.1: resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==} engines: {node: '>= 12.0.0'} @@ -20640,6 +20750,9 @@ packages: stylis@4.2.0: resolution: {integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==} + stylis@4.3.2: + resolution: {integrity: sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg==} + stylus-lookup@5.0.1: resolution: {integrity: sha512-tLtJEd5AGvnVy4f9UHQMw4bkJJtaAcmo54N+ovQBjDY3DuWyK9Eltxzr5+KG0q4ew6v2EHyuWWNnHeiw/Eo7rQ==} engines: {node: '>=14'} @@ -22128,6 +22241,7 @@ packages: web3-provider-engine@14.2.1: resolution: {integrity: sha512-iSv31h2qXkr9vrL6UZDm4leZMc32SjWJFGOp/D92JXfcEboCqraZyuExDkpxKw8ziTufXieNM7LSXNHzszYdJw==} + deprecated: 'This package has been deprecated, see the README for details: https://github.com/MetaMask/web3-provider-engine' web3-providers-http@1.10.3: resolution: {integrity: sha512-6dAgsHR3MxJ0Qyu3QLFlQEelTapVfWNTu5F45FYh8t7Y03T1/o+YAkVxsbY5AdmD+y5bXG/XPJ4q8tjL6MgZHw==} @@ -25948,6 +26062,16 @@ snapshots: '@ctrl/tinycolor@3.6.1': {} + '@defi.org/web3-candies@5.0.0(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10)': + dependencies: + bignumber.js: 9.1.1 + web3: 1.10.3(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10) + transitivePeerDependencies: + - bufferutil + - encoding + - supports-color + - utf-8-validate + '@dependents/detective-less@4.1.0': dependencies: gonzales-pe: 4.3.0 @@ -26017,11 +26141,19 @@ snapshots: '@emotion/memoize': 0.7.4 optional: true + '@emotion/is-prop-valid@1.2.2': + dependencies: + '@emotion/memoize': 0.8.1 + '@emotion/memoize@0.7.4': optional: true + '@emotion/memoize@0.8.1': {} + '@emotion/unitless@0.7.5': {} + '@emotion/unitless@0.8.1': {} + '@emotion/use-insertion-effect-with-fallbacks@1.0.1(react@18.2.0)': dependencies: react: 18.2.0 @@ -27654,7 +27786,7 @@ snapshots: - supports-color - utf-8-validate - '@metamask/sdk@0.27.0(bufferutil@4.0.8)(react@18.2.0)(utf-8-validate@5.0.10)': + '@metamask/sdk@0.27.0(bufferutil@4.0.8)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(utf-8-validate@5.0.10)': dependencies: '@metamask/onboarding': 1.0.1 '@metamask/providers': 16.1.0 @@ -27680,6 +27812,7 @@ snapshots: uuid: 8.3.2 optionalDependencies: react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) transitivePeerDependencies: - bufferutil - encoding @@ -28876,6 +29009,46 @@ snapshots: '@openzeppelin/contracts@4.9.3': {} + '@orbs-network/twap-ui-sushiswap@1.1.21(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react-native@0.73.7(@babel/core@7.24.4)(@babel/preset-env@7.24.4(@babel/core@7.24.4))(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(utf-8-validate@5.0.10))(react@18.2.0)(utf-8-validate@5.0.10)': + dependencies: + '@orbs-network/twap': 2.2.1 + '@orbs-network/twap-ui': 1.1.21(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react-native@0.73.7(@babel/core@7.24.4)(@babel/preset-env@7.24.4(@babel/core@7.24.4))(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(utf-8-validate@5.0.10))(react@18.2.0)(utf-8-validate@5.0.10) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + web3: 1.10.3(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10) + transitivePeerDependencies: + - bufferutil + - encoding + - react-native + - supports-color + - utf-8-validate + + '@orbs-network/twap-ui@1.1.21(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react-native@0.73.7(@babel/core@7.24.4)(@babel/preset-env@7.24.4(@babel/core@7.24.4))(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(utf-8-validate@5.0.10))(react@18.2.0)(utf-8-validate@5.0.10)': + dependencies: + '@defi.org/web3-candies': 5.0.0(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10) + '@orbs-network/twap': 2.2.1 + '@react-icons/all-files': 4.1.0(react@18.2.0) + '@tanstack/react-query': 4.36.1(react-dom@18.2.0(react@18.2.0))(react-native@0.73.7(@babel/core@7.24.4)(@babel/preset-env@7.24.4(@babel/core@7.24.4))(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(utf-8-validate@5.0.10))(react@18.2.0) + bignumber.js: 9.1.1 + moment: 2.29.4 + qrcode.react: 3.1.0(react@18.2.0) + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-error-boundary: 4.0.13(react@18.2.0) + react-number-format: 5.4.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + react-virtualized-auto-sizer: 1.0.24(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + react-window: 1.8.10(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + styled-components: 6.1.12(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + web3: 1.10.3(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10) + transitivePeerDependencies: + - bufferutil + - encoding + - react-native + - supports-color + - utf-8-validate + + '@orbs-network/twap@2.2.1': {} + '@pancakeswap/v3-core@1.0.2': {} '@pancakeswap/v3-periphery@1.0.2': @@ -29925,6 +30098,10 @@ snapshots: '@react-hook/throttle': 2.2.0(react@18.2.0) react: 18.2.0 + '@react-icons/all-files@4.1.0(react@18.2.0)': + dependencies: + react: 18.2.0 + '@react-native-community/cli-clean@12.3.6(encoding@0.1.13)': dependencies: '@react-native-community/cli-tools': 12.3.6(encoding@0.1.13) @@ -31370,7 +31547,7 @@ snapshots: '@stablelib/random': 1.0.2 '@stablelib/wipe': 1.0.1 - '@steerprotocol/contracts@2.1.0-beta.14(bufferutil@4.0.8)(encoding@0.1.13)(squirrelly@8.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)': + '@steerprotocol/contracts@2.1.0-beta.14(bufferutil@4.0.8)(squirrelly@8.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)': dependencies: '@atixlabs/hardhat-time-n-mine': 0.0.5(hardhat@2.20.1(bufferutil@4.0.8)(ts-node@10.9.2(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5)(utf-8-validate@5.0.10)) '@pancakeswap/v3-core': 1.0.2 @@ -32526,6 +32703,8 @@ snapshots: '@tanstack/query-core@4.27.0': {} + '@tanstack/query-core@4.36.1': {} + '@tanstack/query-core@5.51.16': {} '@tanstack/query-persist-client-core@4.27.0': @@ -32546,6 +32725,15 @@ snapshots: '@tanstack/query-persist-client-core': 4.27.0 '@tanstack/react-query': 5.51.16(react@18.2.0) + '@tanstack/react-query@4.36.1(react-dom@18.2.0(react@18.2.0))(react-native@0.73.7(@babel/core@7.24.4)(@babel/preset-env@7.24.4(@babel/core@7.24.4))(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(utf-8-validate@5.0.10))(react@18.2.0)': + dependencies: + '@tanstack/query-core': 4.36.1 + react: 18.2.0 + use-sync-external-store: 1.2.0(react@18.2.0) + optionalDependencies: + react-dom: 18.2.0(react@18.2.0) + react-native: 0.73.7(@babel/core@7.24.4)(@babel/preset-env@7.24.4(@babel/core@7.24.4))(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(utf-8-validate@5.0.10) + '@tanstack/react-query@5.51.16(react@18.2.0)': dependencies: '@tanstack/query-core': 5.51.16 @@ -33325,6 +33513,8 @@ snapshots: '@types/stack-utils@2.0.1': {} + '@types/stylis@4.2.5': {} + '@types/supports-color@8.1.1': {} '@types/tough-cookie@4.0.2': {} @@ -34040,14 +34230,14 @@ snapshots: - utf-8-validate - zod - '@wagmi/connectors@5.1.2(@types/react@18.2.14)(@wagmi/core@2.13.1(@tanstack/query-core@5.51.16)(@types/react@18.2.14)(immer@9.0.21)(react@18.2.0)(typescript@5.4.5)(viem@2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8)))(bufferutil@4.0.8)(react@18.2.0)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8)': + '@wagmi/connectors@5.1.2(@types/react@18.2.14)(@wagmi/core@2.13.1(@tanstack/query-core@5.51.16)(@types/react@18.2.14)(immer@9.0.21)(react@18.2.0)(typescript@5.4.5)(viem@2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8)))(bufferutil@4.0.8)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8)': dependencies: '@coinbase/wallet-sdk': 4.0.4 - '@metamask/sdk': 0.27.0(bufferutil@4.0.8)(react@18.2.0)(utf-8-validate@5.0.10) + '@metamask/sdk': 0.27.0(bufferutil@4.0.8)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(utf-8-validate@5.0.10) '@safe-global/safe-apps-provider': 0.18.3(bufferutil@4.0.8)(encoding@0.1.13)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8) '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.0.8)(encoding@0.1.13)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8) '@wagmi/core': 2.13.1(@tanstack/query-core@5.51.16)(@types/react@18.2.14)(immer@9.0.21)(react@18.2.0)(typescript@5.4.5)(viem@2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8)) - '@walletconnect/ethereum-provider': 2.14.0(@types/react@18.2.14)(bufferutil@4.0.8)(react@18.2.0)(utf-8-validate@5.0.10) + '@walletconnect/ethereum-provider': 2.14.0(@types/react@18.2.14)(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(utf-8-validate@5.0.10) '@walletconnect/modal': 2.6.2(@types/react@18.2.14)(react@18.2.0) cbw-sdk: '@coinbase/wallet-sdk@3.9.3' viem: 2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8) @@ -34077,43 +34267,6 @@ snapshots: - utf-8-validate - zod - '@wagmi/connectors@5.1.2(@types/react@18.2.14)(@wagmi/core@2.13.1(@tanstack/query-core@5.51.16)(@types/react@18.2.14)(immer@9.0.21)(react@18.2.0)(typescript@5.4.5)(viem@2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@6.0.3)(zod@3.23.8)))(bufferutil@4.0.8)(react@18.2.0)(typescript@5.4.5)(utf-8-validate@6.0.3)(viem@2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@6.0.3)(zod@3.23.8))(zod@3.23.8)': - dependencies: - '@coinbase/wallet-sdk': 4.0.4 - '@metamask/sdk': 0.27.0(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(rollup@2.78.0)(utf-8-validate@6.0.3) - '@safe-global/safe-apps-provider': 0.18.3(bufferutil@4.0.8)(encoding@0.1.13)(typescript@5.4.5)(utf-8-validate@6.0.3)(zod@3.23.8) - '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.0.8)(encoding@0.1.13)(typescript@5.4.5)(utf-8-validate@6.0.3)(zod@3.23.8) - '@wagmi/core': 2.13.1(@tanstack/query-core@5.51.16)(@types/react@18.2.14)(immer@9.0.21)(react@18.2.0)(typescript@5.4.5)(viem@2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@6.0.3)(zod@3.23.8)) - '@walletconnect/ethereum-provider': 2.14.0(@types/react@18.2.14)(bufferutil@4.0.8)(react@18.2.0)(utf-8-validate@6.0.3) - '@walletconnect/modal': 2.6.2(@types/react@18.2.14)(react@18.2.0) - cbw-sdk: '@coinbase/wallet-sdk@3.9.3' - viem: 2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@6.0.3)(zod@3.23.8) - optionalDependencies: - typescript: 5.4.5 - transitivePeerDependencies: - - '@azure/app-configuration' - - '@azure/cosmos' - - '@azure/data-tables' - - '@azure/identity' - - '@azure/keyvault-secrets' - - '@azure/storage-blob' - - '@capacitor/preferences' - - '@netlify/blobs' - - '@planetscale/database' - - '@react-native-async-storage/async-storage' - - '@types/react' - - '@upstash/redis' - - '@vercel/kv' - - bufferutil - - encoding - - react - - react-dom - - react-native - - rollup - - supports-color - - utf-8-validate - - zod - '@wagmi/connectors@5.1.2(@types/react@18.2.14)(@wagmi/core@2.13.1(@tanstack/query-core@5.51.16)(@types/react@18.2.14)(react@18.2.0)(typescript@5.4.5)(viem@2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8)))(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react-native@0.73.7(@babel/core@7.24.4)(@babel/preset-env@7.24.4(@babel/core@7.24.4))(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(utf-8-validate@5.0.10))(react@18.2.0)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8)': dependencies: '@coinbase/wallet-sdk': 4.0.4 @@ -34448,70 +34601,6 @@ snapshots: - supports-color - utf-8-validate - '@walletconnect/ethereum-provider@2.14.0(@types/react@18.2.14)(bufferutil@4.0.8)(react@18.2.0)(utf-8-validate@5.0.10)': - dependencies: - '@walletconnect/jsonrpc-http-connection': 1.0.8(encoding@0.1.13) - '@walletconnect/jsonrpc-provider': 1.0.14 - '@walletconnect/jsonrpc-types': 1.0.4 - '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/modal': 2.6.2(@types/react@18.2.14)(react@18.2.0) - '@walletconnect/sign-client': 2.14.0(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10) - '@walletconnect/types': 2.14.0(@upstash/redis@1.22.1) - '@walletconnect/universal-provider': 2.14.0(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@5.0.10) - '@walletconnect/utils': 2.14.0(@upstash/redis@1.22.1) - events: 3.3.0 - transitivePeerDependencies: - - '@azure/app-configuration' - - '@azure/cosmos' - - '@azure/data-tables' - - '@azure/identity' - - '@azure/keyvault-secrets' - - '@azure/storage-blob' - - '@capacitor/preferences' - - '@netlify/blobs' - - '@planetscale/database' - - '@react-native-async-storage/async-storage' - - '@types/react' - - '@upstash/redis' - - '@vercel/kv' - - bufferutil - - encoding - - react - - supports-color - - utf-8-validate - - '@walletconnect/ethereum-provider@2.14.0(@types/react@18.2.14)(bufferutil@4.0.8)(react@18.2.0)(utf-8-validate@6.0.3)': - dependencies: - '@walletconnect/jsonrpc-http-connection': 1.0.8(encoding@0.1.13) - '@walletconnect/jsonrpc-provider': 1.0.14 - '@walletconnect/jsonrpc-types': 1.0.4 - '@walletconnect/jsonrpc-utils': 1.0.8 - '@walletconnect/modal': 2.6.2(@types/react@18.2.14)(react@18.2.0) - '@walletconnect/sign-client': 2.14.0(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@6.0.3) - '@walletconnect/types': 2.14.0(@upstash/redis@1.22.1) - '@walletconnect/universal-provider': 2.14.0(bufferutil@4.0.8)(encoding@0.1.13)(utf-8-validate@6.0.3) - '@walletconnect/utils': 2.14.0(@upstash/redis@1.22.1) - events: 3.3.0 - transitivePeerDependencies: - - '@azure/app-configuration' - - '@azure/cosmos' - - '@azure/data-tables' - - '@azure/identity' - - '@azure/keyvault-secrets' - - '@azure/storage-blob' - - '@capacitor/preferences' - - '@netlify/blobs' - - '@planetscale/database' - - '@react-native-async-storage/async-storage' - - '@types/react' - - '@upstash/redis' - - '@vercel/kv' - - bufferutil - - encoding - - react - - supports-color - - utf-8-validate - '@walletconnect/events@1.0.1': dependencies: keyvaluestorage-interface: 1.0.0 @@ -36976,6 +37065,8 @@ snapshots: camelcase@7.0.1: {} + camelize@1.0.1: {} + caniuse-api@3.0.0: dependencies: browserslist: 4.23.0 @@ -37763,6 +37854,8 @@ snapshots: postcss: 8.4.23 postcss-selector-parser: 6.0.13 + css-color-keywords@1.0.0: {} + css-declaration-sorter@6.4.1(postcss@8.4.23): dependencies: postcss: 8.4.23 @@ -37837,6 +37930,12 @@ snapshots: domutils: 3.1.0 nth-check: 2.1.1 + css-to-react-native@3.2.0: + dependencies: + camelize: 1.0.1 + css-color-keywords: 1.0.0 + postcss-value-parser: 4.2.0 + css-tree@1.0.0-alpha.37: dependencies: mdn-data: 2.0.4 @@ -45521,6 +45620,8 @@ snapshots: nanoid@3.3.6: {} + nanoid@3.3.7: {} + nanoid@4.0.0: {} nanomatch@1.2.13: @@ -46634,20 +46735,20 @@ snapshots: postcss: 8.4.23 ts-node: 10.9.2(@types/node@22.1.0)(typescript@5.4.5) - postcss-load-config@4.0.1(postcss@8.4.31)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5)): + postcss-load-config@4.0.1(postcss@8.4.38)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5)): dependencies: lilconfig: 2.1.0 yaml: 2.4.1 optionalDependencies: - postcss: 8.4.31 + postcss: 8.4.38 ts-node: 10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5) - postcss-load-config@4.0.1(postcss@8.4.31)(ts-node@10.9.2(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5)): + postcss-load-config@4.0.1(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5)): dependencies: lilconfig: 2.1.0 yaml: 2.4.1 optionalDependencies: - postcss: 8.4.31 + postcss: 8.4.38 ts-node: 10.9.2(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5) postcss-loader@6.2.1(postcss@8.4.23)(webpack@5.91.0): @@ -46949,6 +47050,12 @@ snapshots: picocolors: 1.0.0 source-map-js: 1.2.0 + postcss@8.4.38: + dependencies: + nanoid: 3.3.7 + picocolors: 1.0.0 + source-map-js: 1.2.0 + postgres-array@2.0.0: {} postgres-bytea@1.0.0: {} @@ -47825,6 +47932,11 @@ snapshots: react-dom: 18.2.0(react@18.2.0) react-is: 18.1.0 + react-error-boundary@4.0.13(react@18.2.0): + dependencies: + '@babel/runtime': 7.24.5 + react: 18.2.0 + react-error-overlay@6.0.11: {} react-fast-compare@3.2.2: {} @@ -47920,6 +48032,12 @@ snapshots: - supports-color - utf-8-validate + react-number-format@5.4.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + dependencies: + prop-types: 15.8.1 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-onclickoutside@6.13.0(react-dom@18.2.0(react@18.2.0))(react@18.2.0): dependencies: react: 18.2.0 @@ -48144,11 +48262,23 @@ snapshots: react: 18.2.0 react-dom: 18.2.0(react@18.2.0) + react-virtualized-auto-sizer@1.0.24(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + dependencies: + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-virtualized-auto-sizer@1.0.7(react-dom@18.2.0(react@18.2.0))(react@18.2.0): dependencies: react: 18.2.0 react-dom: 18.2.0(react@18.2.0) + react-window@1.8.10(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + dependencies: + '@babel/runtime': 7.24.5 + memoize-one: 5.2.1 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + react-window@1.8.7(react-dom@18.2.0(react@18.2.0))(react@18.2.0): dependencies: '@babel/runtime': 7.24.4 @@ -49077,6 +49207,8 @@ snapshots: shallow-equal@1.2.1: {} + shallowequal@1.1.0: {} + sharp@0.32.6: dependencies: color: 4.2.3 @@ -49800,6 +49932,20 @@ snapshots: dependencies: webpack: 5.91.0 + styled-components@6.1.12(react-dom@18.2.0(react@18.2.0))(react@18.2.0): + dependencies: + '@emotion/is-prop-valid': 1.2.2 + '@emotion/unitless': 0.8.1 + '@types/stylis': 4.2.5 + css-to-react-native: 3.2.0 + csstype: 3.1.3 + postcss: 8.4.38 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + shallowequal: 1.1.0 + stylis: 4.3.2 + tslib: 2.6.2 + styled-jsx@5.1.1(@babel/core@7.23.2)(babel-plugin-macros@3.1.0)(react@18.2.0): dependencies: client-only: 0.0.1 @@ -49825,6 +49971,8 @@ snapshots: stylis@4.2.0: {} + stylis@4.3.2: {} + stylus-lookup@5.0.1: dependencies: commander: 10.0.1 @@ -50724,7 +50872,7 @@ snapshots: tsort@0.0.1: {} - tsup@7.2.0(@swc/core@1.4.2)(postcss@8.4.31)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5): + tsup@7.2.0(@swc/core@1.4.2)(postcss@8.4.38)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5): dependencies: bundle-require: 4.0.1(esbuild@0.18.20) cac: 6.7.14 @@ -50734,7 +50882,7 @@ snapshots: execa: 5.1.1 globby: 11.1.0 joycon: 3.1.1 - postcss-load-config: 4.0.1(postcss@8.4.31)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5)) + postcss-load-config: 4.0.1(postcss@8.4.38)(ts-node@10.9.1(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5)) resolve-from: 5.0.0 rollup: 3.28.0 source-map: 0.8.0-beta.0 @@ -50742,13 +50890,13 @@ snapshots: tree-kill: 1.2.2 optionalDependencies: '@swc/core': 1.4.2(@swc/helpers@0.5.6) - postcss: 8.4.31 + postcss: 8.4.38 typescript: 5.4.5 transitivePeerDependencies: - supports-color - ts-node - tsup@7.2.0(@swc/core@1.4.2)(postcss@8.4.31)(ts-node@10.9.2(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5): + tsup@7.2.0(@swc/core@1.4.2)(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5))(typescript@5.4.5): dependencies: bundle-require: 4.0.1(esbuild@0.18.20) cac: 6.7.14 @@ -50758,7 +50906,7 @@ snapshots: execa: 5.1.1 globby: 11.1.0 joycon: 3.1.1 - postcss-load-config: 4.0.1(postcss@8.4.31)(ts-node@10.9.2(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5)) + postcss-load-config: 4.0.1(postcss@8.4.38)(ts-node@10.9.2(@swc/core@1.4.2)(@types/node@20.14.14)(typescript@5.4.5)) resolve-from: 5.0.0 rollup: 3.28.0 source-map: 0.8.0-beta.0 @@ -50766,7 +50914,7 @@ snapshots: tree-kill: 1.2.2 optionalDependencies: '@swc/core': 1.4.2(@swc/helpers@0.5.6) - postcss: 8.4.31 + postcss: 8.4.38 typescript: 5.4.5 transitivePeerDependencies: - supports-color @@ -51655,41 +51803,6 @@ snapshots: - utf-8-validate - zod - wagmi@2.12.2(@tanstack/query-core@5.51.16)(@tanstack/react-query@5.51.16(react@18.2.0))(@types/react@18.2.14)(bufferutil@4.0.8)(encoding@0.1.13)(immer@9.0.21)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8): - dependencies: - '@tanstack/react-query': 5.51.16(react@18.2.0) - '@wagmi/connectors': 5.1.2(@types/react@18.2.14)(@wagmi/core@2.13.1(@tanstack/query-core@5.51.16)(@types/react@18.2.14)(react@18.2.0)(typescript@5.4.5)(viem@2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8)))(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react-native@0.73.7(@babel/core@7.24.4)(@babel/preset-env@7.24.4(@babel/core@7.24.4))(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(utf-8-validate@5.0.10))(react@18.2.0)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8) - '@wagmi/core': 2.13.1(@tanstack/query-core@5.51.16)(@types/react@18.2.14)(immer@9.0.21)(react@18.2.0)(typescript@5.4.5)(viem@2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8)) - react: 18.2.0 - use-sync-external-store: 1.2.0(react@18.2.0) - viem: 2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8) - optionalDependencies: - typescript: 5.4.5 - transitivePeerDependencies: - - '@azure/app-configuration' - - '@azure/cosmos' - - '@azure/data-tables' - - '@azure/identity' - - '@azure/keyvault-secrets' - - '@azure/storage-blob' - - '@capacitor/preferences' - - '@netlify/blobs' - - '@planetscale/database' - - '@react-native-async-storage/async-storage' - - '@tanstack/query-core' - - '@types/react' - - '@upstash/redis' - - '@vercel/kv' - - bufferutil - - encoding - - immer - - react-dom - - react-native - - rollup - - supports-color - - utf-8-validate - - zod - wagmi@2.12.2(@tanstack/query-core@5.51.16)(@tanstack/react-query@5.51.16(react@18.2.0))(@types/react@18.2.14)(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react-native@0.73.7(@babel/core@7.24.4)(@babel/preset-env@7.24.4(@babel/core@7.24.4))(bufferutil@4.0.8)(encoding@0.1.13)(react@18.2.0)(utf-8-validate@5.0.10))(react@18.2.0)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8): dependencies: '@tanstack/react-query': 5.51.16(react@18.2.0) @@ -51760,10 +51873,10 @@ snapshots: - utf-8-validate - zod - wagmi@2.12.2(@tanstack/query-core@5.51.16)(@tanstack/react-query@5.51.16(react@18.2.0))(@types/react@18.2.14)(bufferutil@4.0.8)(immer@9.0.21)(react@18.2.0)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8): + wagmi@2.12.2(@tanstack/query-core@5.51.16)(@tanstack/react-query@5.51.16(react@18.2.0))(@types/react@18.2.14)(bufferutil@4.0.8)(immer@9.0.21)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8): dependencies: '@tanstack/react-query': 5.51.16(react@18.2.0) - '@wagmi/connectors': 5.1.2(@types/react@18.2.14)(@wagmi/core@2.13.1(@tanstack/query-core@5.51.16)(@types/react@18.2.14)(immer@9.0.21)(react@18.2.0)(typescript@5.4.5)(viem@2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8)))(bufferutil@4.0.8)(react@18.2.0)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8) + '@wagmi/connectors': 5.1.2(@types/react@18.2.14)(@wagmi/core@2.13.1(@tanstack/query-core@5.51.16)(@types/react@18.2.14)(immer@9.0.21)(react@18.2.0)(typescript@5.4.5)(viem@2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8)))(bufferutil@4.0.8)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(typescript@5.4.5)(utf-8-validate@5.0.10)(viem@2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8))(zod@3.23.8) '@wagmi/core': 2.13.1(@tanstack/query-core@5.51.16)(@types/react@18.2.14)(immer@9.0.21)(react@18.2.0)(typescript@5.4.5)(viem@2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@5.0.10)(zod@3.23.8)) react: 18.2.0 use-sync-external-store: 1.2.0(react@18.2.0) @@ -51798,7 +51911,7 @@ snapshots: wagmi@2.12.2(@tanstack/query-core@5.51.16)(@tanstack/react-query@5.51.16(react@18.2.0))(@types/react@18.2.14)(bufferutil@4.0.8)(immer@9.0.21)(react@18.2.0)(typescript@5.4.5)(utf-8-validate@6.0.3)(viem@2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@6.0.3)(zod@3.23.8))(zod@3.23.8): dependencies: '@tanstack/react-query': 5.51.16(react@18.2.0) - '@wagmi/connectors': 5.1.2(@types/react@18.2.14)(@wagmi/core@2.13.1(@tanstack/query-core@5.51.16)(@types/react@18.2.14)(immer@9.0.21)(react@18.2.0)(typescript@5.4.5)(viem@2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@6.0.3)(zod@3.23.8)))(bufferutil@4.0.8)(react@18.2.0)(typescript@5.4.5)(utf-8-validate@6.0.3)(viem@2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@6.0.3)(zod@3.23.8))(zod@3.23.8) + '@wagmi/connectors': 5.1.2(@types/react@18.2.14)(@wagmi/core@2.13.1(@tanstack/query-core@5.51.16)(@types/react@18.2.14)(react@18.2.0)(typescript@5.4.5)(viem@2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@6.0.3)(zod@3.23.8)))(bufferutil@4.0.8)(encoding@0.1.13)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)(rollup@2.78.0)(typescript@5.4.5)(utf-8-validate@6.0.3)(viem@2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@6.0.3)(zod@3.23.8))(zod@3.23.8) '@wagmi/core': 2.13.1(@tanstack/query-core@5.51.16)(@types/react@18.2.14)(immer@9.0.21)(react@18.2.0)(typescript@5.4.5)(viem@2.18.6(bufferutil@4.0.8)(typescript@5.4.5)(utf-8-validate@6.0.3)(zod@3.23.8)) react: 18.2.0 use-sync-external-store: 1.2.0(react@18.2.0)