From b66148442ba0535d13fa3198b137f8922fb47b58 Mon Sep 17 00:00:00 2001 From: Grandschtroumpf Date: Fri, 5 Jun 2026 11:07:42 +0200 Subject: [PATCH 1/8] add carbon router and batchCreate --- package.json | 2 +- src/abis/CarbonRouter.json | 471 +++++++++++++++++++++++++++++ src/contracts-api/Composer.ts | 55 +++- src/contracts-api/Contracts.ts | 15 + src/contracts-api/config.ts | 1 + src/contracts-api/types.ts | 1 + src/strategy-management/Toolkit.ts | 131 +++++++- 7 files changed, 661 insertions(+), 15 deletions(-) create mode 100644 src/abis/CarbonRouter.json diff --git a/package.json b/package.json index 18e66db..460329c 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,7 @@ "types": "dist/index.d.ts", "scripts": { "clean": "rm -rf dist && rm -rf src/abis/types", - "compile-abis": "typechain --target ethers-v6 --out-dir 'src/abis/types' 'src/abis/**/*.json'", + "compile-abis": "typechain --target ethers-v6 --out-dir \"src/abis/types\" \"src/abis/**/*.json\"", "prebuild": "yarn clean && yarn compile-abis", "build": "yarn lint && rollup -c", "test": "yarn lint && mocha", diff --git a/src/abis/CarbonRouter.json b/src/abis/CarbonRouter.json new file mode 100644 index 0000000..1bf5c2e --- /dev/null +++ b/src/abis/CarbonRouter.json @@ -0,0 +1,471 @@ +{ + "address": "0x654a1a16f10d73567920ad803c54e03b0f4c6c81", + "abi": [ + { + "type": "constructor", + "name": "", + "stateMutability": "", + "constant": false, + "inputs": [ + { + "type": "address", + "name": "carbonVoucherInit", + "simpleType": "address" + }, + { + "type": "address", + "name": "gradientVoucherInit", + "simpleType": "address" + } + ], + "id": "e4ba6aa4-752c-48ad-ae1f-d2c7329d4400" + }, + { + "type": "function", + "name": "initialize", + "stateMutability": "nonpayable", + "constant": false, + "id": "0x8129fc1c" + }, + { + "type": "function", + "name": "postUpgrade", + "stateMutability": "nonpayable", + "constant": false, + "inputs": [ + { "type": "bool", "name": "checkVersion", "simpleType": "bool" }, + { "type": "bytes", "name": "data", "simpleType": "bytes" } + ], + "id": "0xdebcf1fe" + }, + { + "type": "function", + "name": "revokeRole", + "stateMutability": "nonpayable", + "constant": false, + "inputs": [ + { "type": "bytes32", "name": "role", "simpleType": "bytes" }, + { "type": "address", "name": "account", "simpleType": "address" } + ], + "id": "0xd547741f" + }, + { + "type": "function", + "name": "getRoleMemberCount", + "stateMutability": "view", + "constant": false, + "inputs": [{ "type": "bytes32", "name": "role", "simpleType": "bytes" }], + "outputs": [{ "type": "uint256", "name": "", "simpleType": "uint" }], + "id": "0xca15c873" + }, + { + "type": "function", + "name": "getRoleMember", + "stateMutability": "view", + "constant": false, + "inputs": [ + { "type": "bytes32", "name": "role", "simpleType": "bytes" }, + { "type": "uint256", "name": "index", "simpleType": "uint" } + ], + "outputs": [{ "type": "address", "name": "", "simpleType": "address" }], + "id": "0x9010d07c" + }, + { + "type": "function", + "name": "onERC721Received", + "stateMutability": "pure", + "constant": false, + "inputs": [ + { "type": "address", "name": "", "simpleType": "address" }, + { "type": "address", "name": "", "simpleType": "address" }, + { "type": "uint256", "name": "", "simpleType": "uint" }, + { "type": "bytes", "name": "", "simpleType": "bytes" } + ], + "outputs": [{ "type": "bytes4", "name": "", "simpleType": "bytes" }], + "id": "0x150b7a02" + }, + { + "type": "function", + "name": "version", + "stateMutability": "pure", + "constant": false, + "outputs": [{ "type": "uint16", "name": "", "simpleType": "uint" }], + "id": "0x54fd4d50" + }, + { + "type": "function", + "name": "batchTradeByTargetAmount", + "stateMutability": "payable", + "constant": false, + "inputs": [ + { + "type": "tuple[]", + "name": "trades", + "simpleType": "slice", + "nestedType": { "type": "tuple" }, + "components": [ + { + "type": "address", + "name": "sourceToken", + "simpleType": "address" + }, + { + "type": "address", + "name": "targetToken", + "simpleType": "address" + }, + { + "type": "tuple[]", + "name": "tradeActions", + "simpleType": "slice", + "nestedType": { "type": "tuple" }, + "components": [ + { + "type": "uint256", + "name": "strategyId", + "simpleType": "uint" + }, + { "type": "uint128", "name": "amount", "simpleType": "uint" } + ] + }, + { "type": "uint256", "name": "deadline", "simpleType": "uint" }, + { "type": "uint128", "name": "maxInput", "simpleType": "uint" }, + { "type": "uint16", "name": "controllerType", "simpleType": "uint" } + ] + } + ], + "id": "0x89562094" + }, + { + "type": "function", + "name": "roleAdmin", + "stateMutability": "pure", + "constant": false, + "outputs": [{ "type": "bytes32", "name": "", "simpleType": "bytes" }], + "id": "0x93867fb5" + }, + { + "type": "function", + "name": "grantRole", + "stateMutability": "nonpayable", + "constant": false, + "inputs": [ + { "type": "bytes32", "name": "role", "simpleType": "bytes" }, + { "type": "address", "name": "account", "simpleType": "address" } + ], + "id": "0x2f2ff15d" + }, + { + "type": "function", + "name": "supportsInterface", + "stateMutability": "view", + "constant": false, + "inputs": [ + { "type": "bytes4", "name": "interfaceId", "simpleType": "bytes" } + ], + "outputs": [{ "type": "bool", "name": "", "simpleType": "bool" }], + "id": "0x01ffc9a7" + }, + { + "type": "function", + "name": "DEFAULT_ADMIN_ROLE", + "stateMutability": "view", + "constant": false, + "outputs": [{ "type": "bytes32", "name": "", "simpleType": "bytes" }], + "id": "0xa217fddf" + }, + { + "type": "function", + "name": "getRoleAdmin", + "stateMutability": "view", + "constant": false, + "inputs": [{ "type": "bytes32", "name": "role", "simpleType": "bytes" }], + "outputs": [{ "type": "bytes32", "name": "", "simpleType": "bytes" }], + "id": "0x248a9ca3" + }, + { + "type": "function", + "name": "batchTradeBySourceAmount", + "stateMutability": "payable", + "constant": false, + "inputs": [ + { + "type": "tuple[]", + "name": "trades", + "simpleType": "slice", + "nestedType": { "type": "tuple" }, + "components": [ + { + "type": "address", + "name": "sourceToken", + "simpleType": "address" + }, + { + "type": "address", + "name": "targetToken", + "simpleType": "address" + }, + { + "type": "tuple[]", + "name": "tradeActions", + "simpleType": "slice", + "nestedType": { "type": "tuple" }, + "components": [ + { + "type": "uint256", + "name": "strategyId", + "simpleType": "uint" + }, + { "type": "uint128", "name": "amount", "simpleType": "uint" } + ] + }, + { "type": "uint256", "name": "deadline", "simpleType": "uint" }, + { "type": "uint128", "name": "minReturn", "simpleType": "uint" }, + { "type": "uint16", "name": "controllerType", "simpleType": "uint" } + ] + } + ], + "id": "0xd63b3b8a" + }, + { + "type": "function", + "name": "batchCreate", + "stateMutability": "payable", + "constant": false, + "inputs": [ + { + "type": "tuple[]", + "name": "strategies", + "simpleType": "slice", + "nestedType": { "type": "tuple" }, + "components": [ + { + "type": "address[2]", + "name": "tokens", + "simpleType": "array", + "nestedType": { "type": "address" } + }, + { + "type": "tuple[2]", + "name": "orders", + "simpleType": "array", + "nestedType": { "type": "tuple" }, + "components": [ + { "type": "uint128", "name": "y", "simpleType": "uint" }, + { "type": "uint128", "name": "z", "simpleType": "uint" }, + { "type": "uint64", "name": "A", "simpleType": "uint" }, + { "type": "uint64", "name": "B", "simpleType": "uint" } + ] + } + ] + }, + { + "type": "tuple[]", + "name": "gradientStrategies", + "simpleType": "slice", + "nestedType": { "type": "tuple" }, + "components": [ + { + "type": "address[2]", + "name": "tokens", + "simpleType": "array", + "nestedType": { "type": "address" } + }, + { + "type": "tuple[2]", + "name": "orders", + "simpleType": "array", + "nestedType": { "type": "tuple" }, + "components": [ + { + "type": "uint128", + "name": "liquidity", + "simpleType": "uint" + }, + { + "type": "uint64", + "name": "initialPrice", + "simpleType": "uint" + }, + { + "type": "uint32", + "name": "tradingStartTime", + "simpleType": "uint" + }, + { "type": "uint32", "name": "expiry", "simpleType": "uint" }, + { + "type": "uint32", + "name": "multiFactor", + "simpleType": "uint" + }, + { + "type": "uint8", + "name": "gradientType", + "simpleType": "uint" + } + ] + } + ] + } + ], + "outputs": [ + { + "type": "uint256[]", + "name": "", + "simpleType": "slice", + "nestedType": { "type": "uint", "count": 256 } + }, + { + "type": "uint256[]", + "name": "", + "simpleType": "slice", + "nestedType": { "type": "uint", "count": 256 } + } + ], + "id": "0x144ea82e" + }, + { + "type": "function", + "name": "hasRole", + "stateMutability": "view", + "constant": false, + "inputs": [ + { "type": "bytes32", "name": "role", "simpleType": "bytes" }, + { "type": "address", "name": "account", "simpleType": "address" } + ], + "outputs": [{ "type": "bool", "name": "", "simpleType": "bool" }], + "id": "0x91d14854" + }, + { + "type": "function", + "name": "renounceRole", + "stateMutability": "nonpayable", + "constant": false, + "inputs": [ + { "type": "bytes32", "name": "role", "simpleType": "bytes" }, + { "type": "address", "name": "account", "simpleType": "address" } + ], + "id": "0x36568abe" + }, + { + "type": "function", + "name": "withdrawFunds", + "stateMutability": "nonpayable", + "constant": false, + "inputs": [ + { "type": "address", "name": "token", "simpleType": "address" }, + { "type": "address", "name": "target", "simpleType": "address" }, + { "type": "uint256", "name": "amount", "simpleType": "uint" } + ], + "id": "0x1c20fadd" + }, + { + "type": "function", + "name": "withdrawNFT", + "stateMutability": "nonpayable", + "constant": false, + "inputs": [ + { "type": "uint16", "name": "controllerType", "simpleType": "uint" }, + { "type": "uint256", "name": "tokenId", "simpleType": "uint" }, + { "type": "address", "name": "target", "simpleType": "address" } + ], + "id": "0xf365bc8a" + }, + { + "type": "event", + "name": "RoleGranted", + "stateMutability": "", + "constant": false, + "inputs": [ + { "type": "bytes32", "name": "role", "simpleType": "bytes" }, + { "type": "address", "name": "account", "simpleType": "address" }, + { "type": "address", "name": "sender", "simpleType": "address" } + ], + "id": "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d" + }, + { + "type": "event", + "name": "RoleRevoked", + "stateMutability": "", + "constant": false, + "inputs": [ + { "type": "bytes32", "name": "role", "simpleType": "bytes" }, + { "type": "address", "name": "account", "simpleType": "address" }, + { "type": "address", "name": "sender", "simpleType": "address" } + ], + "id": "0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b" + }, + { + "type": "event", + "name": "StrategiesCreated", + "stateMutability": "", + "constant": false, + "inputs": [ + { "type": "address", "name": "owner", "simpleType": "address" }, + { + "type": "uint256[]", + "name": "strategyIds", + "simpleType": "slice", + "nestedType": { "type": "uint", "count": 256 } + }, + { + "type": "uint256[]", + "name": "gradientStrategyIds", + "simpleType": "slice", + "nestedType": { "type": "uint", "count": 256 } + } + ], + "id": "0xf420980ae6459276d91c7e51a10c1e6bf711628543fea7ee7c0ab260aa7fb6e8" + }, + { + "type": "event", + "name": "FundsWithdrawn", + "stateMutability": "", + "constant": false, + "inputs": [ + { "type": "address", "name": "token", "simpleType": "address" }, + { "type": "address", "name": "caller", "simpleType": "address" }, + { "type": "address", "name": "target", "simpleType": "address" }, + { "type": "uint256", "name": "amount", "simpleType": "uint" } + ], + "id": "0xc322efa58c9cb2c39cfffdac61d35c8643f5cbf13c6a7d0034de2cf18923aff3" + }, + { + "type": "event", + "name": "Initialized", + "stateMutability": "", + "constant": false, + "inputs": [{ "type": "uint8", "name": "version", "simpleType": "uint" }], + "id": "0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498" + }, + { + "type": "event", + "name": "NFTWithdrawn", + "stateMutability": "", + "constant": false, + "inputs": [ + { "type": "uint16", "name": "controllerType", "simpleType": "uint" }, + { "type": "uint256", "name": "tokenId", "simpleType": "uint" }, + { "type": "address", "name": "caller", "simpleType": "address" }, + { "type": "address", "name": "target", "simpleType": "address" } + ], + "id": "0x0fd532ac4d780682db2e44d81e24740f2e15526d3c7d385b3b4f447ef3cbee7f" + }, + { + "type": "event", + "name": "RoleAdminChanged", + "stateMutability": "", + "constant": false, + "inputs": [ + { "type": "bytes32", "name": "role", "simpleType": "bytes" }, + { + "type": "bytes32", + "name": "previousAdminRole", + "simpleType": "bytes" + }, + { "type": "bytes32", "name": "newAdminRole", "simpleType": "bytes" } + ], + "id": "0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff" + } + ] +} diff --git a/src/contracts-api/Composer.ts b/src/contracts-api/Composer.ts index 1b74d76..e1dae20 100644 --- a/src/contracts-api/Composer.ts +++ b/src/contracts-api/Composer.ts @@ -135,10 +135,50 @@ export default class Composer { order1: EncodedOrder; }[], overrides?: PayableOverrides + ): Promise; + + public batchCreateStrategies( + strategies: { + token0: string; + token1: string; + order0: EncodedOrder; + order1: EncodedOrder; + }[], + gradientStrategies: { + token0: string; + token1: string; + order0: EncodedGradientOrder; + order1: EncodedGradientOrder; + }[], + overrides?: PayableOverrides + ): Promise; + + public batchCreateStrategies( + strategies: { + token0: string; + token1: string; + order0: EncodedOrder; + order1: EncodedOrder; + }[], + gradientStrategiesOrOverrides?: + | { + token0: string; + token1: string; + order0: EncodedGradientOrder; + order1: EncodedGradientOrder; + }[] + | PayableOverrides, + overrides?: PayableOverrides ) { logger.debug('batchCreateStrategies called', arguments); - const customOverrides = { ...overrides }; + const gradientStrategies = Array.isArray(gradientStrategiesOrOverrides) + ? gradientStrategiesOrOverrides + : []; + const customOverrides = Array.isArray(gradientStrategiesOrOverrides) + ? { ...overrides } + : { ...gradientStrategiesOrOverrides }; + let nativeTokenValue = 0n; // for each order using native token, sum the its y value into customOverrides.value for (const strategy of strategies) { @@ -148,17 +188,28 @@ export default class Composer { nativeTokenValue = nativeTokenValue + strategy.order1.y; } } + for (const strategy of gradientStrategies) { + if (isETHAddress(strategy.token0)) { + nativeTokenValue = nativeTokenValue + strategy.order0.liquidity; + } else if (isETHAddress(strategy.token1)) { + nativeTokenValue = nativeTokenValue + strategy.order1.liquidity; + } + } if (nativeTokenValue > 0n) { customOverrides.value = nativeTokenValue; } logger.debug('batchCreateStrategies overrides', customOverrides); - return this._contracts.carbonBatcher.batchCreate.populateTransaction( + return this._contracts.carbonRouter.batchCreate.populateTransaction( strategies.map((s) => ({ tokens: [s.token0, s.token1], orders: [s.order0, s.order1], })), + gradientStrategies.map((s) => ({ + tokens: [s.token0, s.token1], + orders: [s.order0, s.order1], + })), customOverrides ); } diff --git a/src/contracts-api/Contracts.ts b/src/contracts-api/Contracts.ts index 5f88340..ec15e3c 100644 --- a/src/contracts-api/Contracts.ts +++ b/src/contracts-api/Contracts.ts @@ -1,6 +1,8 @@ import { CarbonController__factory, CarbonController, + CarbonRouter, + CarbonRouter__factory, GradientController, GradientController__factory, GradientVoucher, @@ -27,6 +29,7 @@ export class Contracts { private _multiCall: Multicall | undefined; private _voucher: Voucher | undefined; private _carbonBatcher: CarbonBatcher | undefined; + private _carbonRouter: CarbonRouter | undefined; private _config = defaultConfig; public constructor(provider: Provider, config?: ContractsConfig) { @@ -39,6 +42,8 @@ export class Contracts { config?.voucherAddress || defaultConfig.voucherAddress; this._config.carbonBatcherAddress = config?.carbonBatcherAddress || defaultConfig.carbonBatcherAddress; + this._config.carbonRouterAddress = + config?.carbonRouterAddress || defaultConfig.carbonRouterAddress; this._config.gradientControllerAddress = config?.gradientControllerAddress ?? defaultConfig.gradientControllerAddress; @@ -84,6 +89,16 @@ export class Contracts { return this._carbonBatcher; } + public get carbonRouter(): CarbonRouter { + if (!this._carbonRouter) + this._carbonRouter = CarbonRouter__factory.connect( + this._config.carbonRouterAddress, + this._provider + ); + + return this._carbonRouter; + } + public get multicall(): Multicall { if (!this._multiCall) this._multiCall = Multicall__factory.connect( diff --git a/src/contracts-api/config.ts b/src/contracts-api/config.ts index 4e8f0b1..e95c016 100644 --- a/src/contracts-api/config.ts +++ b/src/contracts-api/config.ts @@ -5,6 +5,7 @@ export const config: Required = { multiCallAddress: '0x5ba1e12693dc8f9c48aad8770482f4739beed696', voucherAddress: '0x3660F04B79751e31128f6378eAC70807e38f554E', carbonBatcherAddress: '0x0199f3A6C4B192B9f9C3eBE31FBC535CdD4B7D4e', + carbonRouterAddress: '0x654a1a16f10d73567920ad803c54e03b0f4c6c81', gradientControllerAddress: '0x37A65Dda75A4C32959834C9b391a24dCa17eeC10', gradientVoucherAddress: '0x63e353AE90f95C72bf1E78e45456fb78B0c97525', }; diff --git a/src/contracts-api/types.ts b/src/contracts-api/types.ts index f2a523e..6f0bf44 100644 --- a/src/contracts-api/types.ts +++ b/src/contracts-api/types.ts @@ -3,6 +3,7 @@ export type ContractsConfig = { multiCallAddress?: string; voucherAddress?: string; carbonBatcherAddress?: string; + carbonRouterAddress?: string; gradientControllerAddress?: string; gradientVoucherAddress?: string; }; diff --git a/src/strategy-management/Toolkit.ts b/src/strategy-management/Toolkit.ts index 2c2ccbb..dea6707 100644 --- a/src/strategy-management/Toolkit.ts +++ b/src/strategy-management/Toolkit.ts @@ -107,6 +107,36 @@ export type TradeData = { actionsWei: MatchActionBNStr[]; }; +export type BatchCreateBuySellStrategy = { + baseToken: string; + quoteToken: string; + buyPriceLow: string; + buyPriceMarginal: string; + buyPriceHigh: string; + buyBudget: string; + sellPriceLow: string; + sellPriceMarginal: string; + sellPriceHigh: string; + sellBudget: string; +}; + +export type BatchCreateGradientStrategy = { + baseToken: string; + quoteToken: string; + buyInitialPrice: string; + buyFinalPrice: string; + buyBudget: string; + buyTradingStartTime: number; + buyTradingEndTime: number; + buyGradientType: GradientType; + sellInitialPrice: string; + sellFinalPrice: string; + sellBudget: string; + sellTradingStartTime: number; + sellTradingEndTime: number; + sellGradientType: GradientType; +}; + type StaticTradeDataBaseParams = { amount: string; isTradeByTarget: boolean; @@ -1351,18 +1381,7 @@ export class Toolkit { * @returns {Promise} A promise that resolves to the unsigned transaction that can be used to create the strategies. */ public async batchCreateBuySellStrategies( - strategies: { - baseToken: string; - quoteToken: string; - buyPriceLow: string; - buyPriceMarginal: string; - buyPriceHigh: string; - buyBudget: string; - sellPriceLow: string; - sellPriceMarginal: string; - sellPriceHigh: string; - sellBudget: string; - }[], + strategies: BatchCreateBuySellStrategy[], overrides?: PayableOverrides ): Promise { logger.debug('batchCreateBuySellStrategies called', arguments); @@ -1398,6 +1417,94 @@ export class Toolkit { return this._api.composer.batchCreateStrategies(encStrategies, overrides); } + /** + * Creates an unsigned transaction to create multiple regular and gradient strategies in a single batch. + * + * @param {BatchCreateBuySellStrategy[]} strategies - An array of regular buy/sell strategies to create. + * @param {BatchCreateGradientStrategy[]} gradientStrategies - An array of gradient strategies to create. + * @param {PayableOverrides} [overrides] - Optional overrides for the transaction, such as gas price or nonce. + * @returns {Promise} A promise that resolves to the unsigned transaction that can be used to create the strategies. + */ + public async batchCreateStrategies( + strategies: BatchCreateBuySellStrategy[], + gradientStrategies: BatchCreateGradientStrategy[], + overrides?: PayableOverrides + ): Promise { + logger.debug('batchCreateStrategies called', arguments); + const decimals = this._decimals; + + const encStrategies = await Promise.all( + strategies.map(async (s) => { + const baseDecimals = await decimals.fetchDecimals(s.baseToken); + const quoteDecimals = await decimals.fetchDecimals(s.quoteToken); + const strategy: DecodedStrategy = buildStrategyObject( + s.baseToken, + s.quoteToken, + baseDecimals, + quoteDecimals, + s.buyPriceLow, + s.buyPriceMarginal, + s.buyPriceHigh, + s.buyBudget, + s.sellPriceLow, + s.sellPriceMarginal, + s.sellPriceHigh, + s.sellBudget + ); + const encStrategy = encodeStrategy(strategy); + return { + token0: encStrategy.token0, + token1: encStrategy.token1, + order0: encStrategy.order0, + order1: encStrategy.order1, + }; + }) + ); + + const encGradientStrategies = await Promise.all( + gradientStrategies.map(async (s) => { + const baseDecimals = await decimals.fetchDecimals(s.baseToken); + const quoteDecimals = await decimals.fetchDecimals(s.quoteToken); + const strategy: DecodedGradientStrategy = buildGradientStrategyObject( + s.baseToken, + s.quoteToken, + baseDecimals, + quoteDecimals, + s.buyInitialPrice, + s.buyFinalPrice, + s.buyBudget, + s.buyTradingStartTime, + s.buyTradingEndTime, + s.buyGradientType, + s.sellInitialPrice, + s.sellFinalPrice, + s.sellBudget, + s.sellTradingStartTime, + s.sellTradingEndTime, + s.sellGradientType + ); + const encStrategy = encodeGradientStrategy(strategy); + return { + token0: encStrategy.token0, + token1: encStrategy.token1, + order0: encStrategy.order0, + order1: encStrategy.order1, + }; + }) + ); + + logger.debug('batchCreateStrategies info:', { + encStrategies, + encGradientStrategies, + }); + + return this._api.composer.batchCreateStrategies( + encStrategies, + encGradientStrategies, + overrides + ); + } + /** * Creates an unsigned transaction to update an on chain strategy. * This function takes various optional parameters to update different aspects of the strategy and returns a promise that resolves to a PopulatedTransaction object. From 5452cdec945f28c6bf6b2d19bff3e50642cca7bb Mon Sep 17 00:00:00 2001 From: Grandschtroumpf Date: Fri, 5 Jun 2026 11:27:20 +0200 Subject: [PATCH 2/8] update carbonrouter abis to compile with typechain --- src/abis/CarbonRouter.json | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/abis/CarbonRouter.json b/src/abis/CarbonRouter.json index 1bf5c2e..4545d00 100644 --- a/src/abis/CarbonRouter.json +++ b/src/abis/CarbonRouter.json @@ -25,6 +25,8 @@ "name": "initialize", "stateMutability": "nonpayable", "constant": false, + "inputs": [], + "outputs": [], "id": "0x8129fc1c" }, { @@ -36,6 +38,7 @@ { "type": "bool", "name": "checkVersion", "simpleType": "bool" }, { "type": "bytes", "name": "data", "simpleType": "bytes" } ], + "outputs": [], "id": "0xdebcf1fe" }, { @@ -47,6 +50,7 @@ { "type": "bytes32", "name": "role", "simpleType": "bytes" }, { "type": "address", "name": "account", "simpleType": "address" } ], + "outputs": [], "id": "0xd547741f" }, { @@ -89,6 +93,7 @@ "name": "version", "stateMutability": "pure", "constant": false, + "inputs": [], "outputs": [{ "type": "uint16", "name": "", "simpleType": "uint" }], "id": "0x54fd4d50" }, @@ -134,6 +139,7 @@ ] } ], + "outputs": [], "id": "0x89562094" }, { @@ -141,6 +147,7 @@ "name": "roleAdmin", "stateMutability": "pure", "constant": false, + "inputs": [], "outputs": [{ "type": "bytes32", "name": "", "simpleType": "bytes" }], "id": "0x93867fb5" }, @@ -153,6 +160,7 @@ { "type": "bytes32", "name": "role", "simpleType": "bytes" }, { "type": "address", "name": "account", "simpleType": "address" } ], + "outputs": [], "id": "0x2f2ff15d" }, { @@ -171,6 +179,7 @@ "name": "DEFAULT_ADMIN_ROLE", "stateMutability": "view", "constant": false, + "inputs": [], "outputs": [{ "type": "bytes32", "name": "", "simpleType": "bytes" }], "id": "0xa217fddf" }, @@ -225,6 +234,7 @@ ] } ], + "outputs": [], "id": "0xd63b3b8a" }, { @@ -345,6 +355,7 @@ { "type": "bytes32", "name": "role", "simpleType": "bytes" }, { "type": "address", "name": "account", "simpleType": "address" } ], + "outputs": [], "id": "0x36568abe" }, { @@ -357,6 +368,7 @@ { "type": "address", "name": "target", "simpleType": "address" }, { "type": "uint256", "name": "amount", "simpleType": "uint" } ], + "outputs": [], "id": "0x1c20fadd" }, { @@ -369,6 +381,7 @@ { "type": "uint256", "name": "tokenId", "simpleType": "uint" }, { "type": "address", "name": "target", "simpleType": "address" } ], + "outputs": [], "id": "0xf365bc8a" }, { From 6a52e13f9b4f628560087e3657d954deed5a1e68 Mon Sep 17 00:00:00 2001 From: Grandschtroumpf Date: Fri, 5 Jun 2026 11:30:39 +0200 Subject: [PATCH 3/8] Fix build --- rollup.config.js | 2 +- tests/match.spec.ts | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/rollup.config.js b/rollup.config.js index f990f25..2367477 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -2,7 +2,7 @@ import resolve from '@rollup/plugin-node-resolve'; import commonjs from '@rollup/plugin-commonjs'; import typescript from '@rollup/plugin-typescript'; import { terser } from 'rollup-plugin-terser'; -import pkg from './package.json' assert { type: 'json' }; +import pkg from './package.json' with { type: 'json' }; export default { input: { diff --git a/tests/match.spec.ts b/tests/match.spec.ts index 19039ec..1d16c86 100644 --- a/tests/match.spec.ts +++ b/tests/match.spec.ts @@ -20,10 +20,10 @@ import { // created via https://github.com/bancorprotocol/carbon-simulator/blob/main/benchmark/test_match.py // located at https://github.com/bancorprotocol/carbon-simulator/tree/main/benchmark/resources/match -import ArbitraryMatch from './data/ArbitraryMatch.json' assert { type: 'json' }; -import BigPoolMatch from './data/BigPoolMatch.json' assert { type: 'json' }; -import EthUsdcMatch from './data/EthUsdcMatch.json' assert { type: 'json' }; -import SpecialMatch from './data/SpecialMatch.json' assert { type: 'json' }; +import ArbitraryMatch from './data/ArbitraryMatch.json' with { type: 'json' }; +import BigPoolMatch from './data/BigPoolMatch.json' with { type: 'json' }; +import EthUsdcMatch from './data/EthUsdcMatch.json' with { type: 'json' }; +import SpecialMatch from './data/SpecialMatch.json' with { type: 'json' }; type TradeMethod = (amount: bigint, order: EncodedOrder) => bigint; type MatchMethod = 'matchBySourceAmount' | 'matchByTargetAmount'; From 892fa22e20dc24e60f34bf0d552b72a14c65d1aa Mon Sep 17 00:00:00 2001 From: Grandschtroumpf Date: Fri, 5 Jun 2026 11:53:52 +0200 Subject: [PATCH 4/8] add tests --- tests/toolkit.spec.ts | 140 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 138 insertions(+), 2 deletions(-) diff --git a/tests/toolkit.spec.ts b/tests/toolkit.spec.ts index 0f23b17..2446c49 100644 --- a/tests/toolkit.spec.ts +++ b/tests/toolkit.spec.ts @@ -11,7 +11,9 @@ import { import { encodedStrategyBigIntToStr, ordersMapBNToStr } from '../src/utils'; import { buildGradientStrategyObject, + buildStrategyObject, encodeGradientStrategy, + encodeStrategy, } from '../src/strategy-management/utils'; const encodedStrategies: EncodedStrategy[] = [ @@ -164,6 +166,7 @@ describe('Toolkit', () => { composer: { updateStrategy: sinon.stub(), createStrategy: sinon.stub(), + batchCreateStrategies: sinon.stub(), }, }; cacheMock = sinon.createStubInstance(ChainCache); @@ -1021,6 +1024,135 @@ describe('Toolkit', () => { }); }); + describe('batchCreateStrategies', () => { + const regularStrategies = [ + { + baseToken: 'baseA', + quoteToken: 'quoteA', + buyPriceLow: '1500', + buyPriceMarginal: '1600', + buyPriceHigh: '1700', + buyBudget: '100', + sellPriceLow: '1800', + sellPriceMarginal: '1900', + sellPriceHigh: '2000', + sellBudget: '1', + }, + { + baseToken: 'baseB', + quoteToken: 'quoteB', + buyPriceLow: '2500', + buyPriceMarginal: '2600', + buyPriceHigh: '2700', + buyBudget: '200', + sellPriceLow: '2800', + sellPriceMarginal: '2900', + sellPriceHigh: '3000', + sellBudget: '2', + }, + ]; + + const gradientStrategies = [ + { + baseToken: 'gBase', + quoteToken: 'gQuote', + buyInitialPrice: '1800', + buyFinalPrice: '1900', + buyBudget: '1800', + buyTradingStartTime: 1000000, + buyTradingEndTime: 2000000, + buyGradientType: GradientType.LINEAR_DECREASE, + sellInitialPrice: '2000', + sellFinalPrice: '1900', + sellBudget: '1', + sellTradingStartTime: 1000000, + sellTradingEndTime: 2000000, + sellGradientType: GradientType.LINEAR_INCREASE, + }, + ]; + + it('should encode regular and gradient strategies and pass them to composer.batchCreateStrategies', async () => { + const toolkit = new Toolkit(apiMock, cacheMock, decimalFetcher); + await toolkit.batchCreateStrategies( + regularStrategies, + gradientStrategies + ); + + const args = apiMock.composer.batchCreateStrategies.getCall(0).args; + const expectedRegular = regularStrategies.map((s) => { + const encStrategy = encodeStrategy( + buildStrategyObject( + s.baseToken, + s.quoteToken, + 18, + 18, + s.buyPriceLow, + s.buyPriceMarginal, + s.buyPriceHigh, + s.buyBudget, + s.sellPriceLow, + s.sellPriceMarginal, + s.sellPriceHigh, + s.sellBudget + ) + ); + + return { + token0: encStrategy.token0, + token1: encStrategy.token1, + order0: encStrategy.order0, + order1: encStrategy.order1, + }; + }); + + const expectedGradient = gradientStrategies.map((s) => { + const encStrategy = encodeGradientStrategy( + buildGradientStrategyObject( + s.baseToken, + s.quoteToken, + 18, + 18, + s.buyInitialPrice, + s.buyFinalPrice, + s.buyBudget, + s.buyTradingStartTime, + s.buyTradingEndTime, + s.buyGradientType, + s.sellInitialPrice, + s.sellFinalPrice, + s.sellBudget, + s.sellTradingStartTime, + s.sellTradingEndTime, + s.sellGradientType + ) + ); + + return { + token0: encStrategy.token0, + token1: encStrategy.token1, + order0: encStrategy.order0, + order1: encStrategy.order1, + }; + }); + + expect(args[0]).to.deep.equal(expectedRegular); + expect(args[1]).to.deep.equal(expectedGradient); + }); + + it('should pass overrides through as the third argument', async () => { + const overrides = { gasLimit: 123456n }; + const toolkit = new Toolkit(apiMock, cacheMock, decimalFetcher); + await toolkit.batchCreateStrategies( + regularStrategies, + gradientStrategies, + overrides + ); + + const args = apiMock.composer.batchCreateStrategies.getCall(0).args; + expect(args[2]).to.deep.equal(overrides); + }); + }); + describe('deleteGradientStrategy', () => { it('should call deleteGradientStrategy on the composer with the strategy id as bigint', async () => { apiMock.composer.deleteGradientStrategy = sinon.stub().resolves({}); @@ -1423,7 +1555,9 @@ describe('Toolkit', () => { const toolkit = new Toolkit(apiMock, cacheMock, decimalFetcher); // Must not throw - await toolkit.updateGradientStrategy('42', zeroPriceEncoded, { buyBudget: '100' }); + await toolkit.updateGradientStrategy('42', zeroPriceEncoded, { + buyBudget: '100', + }); const args = apiMock.composer.updateGradientStrategy.getCall(0).args; // The zero-price sell order must pass through unchanged @@ -1431,7 +1565,9 @@ describe('Toolkit', () => { expect(args[4][0].initialPrice).to.equal(0n); expect(args[4][0].multiFactor).to.equal(0); // The buy order liquidity should reflect the new budget - expect(args[4][1].liquidity.toString()).to.equal((100n * 10n ** 18n).toString()); + expect(args[4][1].liquidity.toString()).to.equal( + (100n * 10n ** 18n).toString() + ); }); }); }); From db7acdce33f2cf7a0ff51b2d9243e48337564d48 Mon Sep 17 00:00:00 2001 From: Grandschtroumpf Date: Fri, 5 Jun 2026 14:49:26 +0200 Subject: [PATCH 5/8] reintroduce batcher createStrategies --- src/contracts-api/Composer.ts | 40 ++++++++++++++++++++++++++++-- src/strategy-management/Toolkit.ts | 2 +- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/contracts-api/Composer.ts b/src/contracts-api/Composer.ts index e1dae20..03192b8 100644 --- a/src/contracts-api/Composer.ts +++ b/src/contracts-api/Composer.ts @@ -135,9 +135,45 @@ export default class Composer { order1: EncodedOrder; }[], overrides?: PayableOverrides + ) { + logger.debug('batchCreateStrategies called', arguments); + + const customOverrides = { ...overrides }; + let nativeTokenValue = 0n; + // for each order using native token, sum the its y value into customOverrides.value + for (const strategy of strategies) { + if (isETHAddress(strategy.token0)) { + nativeTokenValue = nativeTokenValue + strategy.order0.y; + } else if (isETHAddress(strategy.token1)) { + nativeTokenValue = nativeTokenValue + strategy.order1.y; + } + } + if (nativeTokenValue > 0n) { + customOverrides.value = nativeTokenValue; + } + + logger.debug('batchCreateStrategies overrides', customOverrides); + + return this._contracts.carbonBatcher.batchCreate.populateTransaction( + strategies.map((s) => ({ + tokens: [s.token0, s.token1], + orders: [s.order0, s.order1], + })), + customOverrides + ); + } + + public routerCreateStrategies( + strategies: { + token0: string; + token1: string; + order0: EncodedOrder; + order1: EncodedOrder; + }[], + overrides?: PayableOverrides ): Promise; - public batchCreateStrategies( + public routerCreateStrategies( strategies: { token0: string; token1: string; @@ -153,7 +189,7 @@ export default class Composer { overrides?: PayableOverrides ): Promise; - public batchCreateStrategies( + public routerCreateStrategies( strategies: { token0: string; token1: string; diff --git a/src/strategy-management/Toolkit.ts b/src/strategy-management/Toolkit.ts index dea6707..4cc2131 100644 --- a/src/strategy-management/Toolkit.ts +++ b/src/strategy-management/Toolkit.ts @@ -1498,7 +1498,7 @@ export class Toolkit { encGradientStrategies, }); - return this._api.composer.batchCreateStrategies( + return this._api.composer.routerCreateStrategies( encStrategies, encGradientStrategies, overrides From f0eea58b4282a82b71530f504cf7e53175e4a8b3 Mon Sep 17 00:00:00 2001 From: Grandschtroumpf Date: Fri, 5 Jun 2026 15:35:30 +0200 Subject: [PATCH 6/8] rename methods --- src/contracts-api/Composer.ts | 4 ++-- src/strategy-management/Toolkit.ts | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/contracts-api/Composer.ts b/src/contracts-api/Composer.ts index 03192b8..ffaa8ac 100644 --- a/src/contracts-api/Composer.ts +++ b/src/contracts-api/Composer.ts @@ -206,7 +206,7 @@ export default class Composer { | PayableOverrides, overrides?: PayableOverrides ) { - logger.debug('batchCreateStrategies called', arguments); + logger.debug('routerCreateStrategies called', arguments); const gradientStrategies = Array.isArray(gradientStrategiesOrOverrides) ? gradientStrategiesOrOverrides @@ -235,7 +235,7 @@ export default class Composer { customOverrides.value = nativeTokenValue; } - logger.debug('batchCreateStrategies overrides', customOverrides); + logger.debug('routerCreateStrategies overrides', customOverrides); return this._contracts.carbonRouter.batchCreate.populateTransaction( strategies.map((s) => ({ diff --git a/src/strategy-management/Toolkit.ts b/src/strategy-management/Toolkit.ts index 4cc2131..46b437f 100644 --- a/src/strategy-management/Toolkit.ts +++ b/src/strategy-management/Toolkit.ts @@ -1425,12 +1425,12 @@ export class Toolkit { * @param {PayableOverrides} [overrides] - Optional overrides for the transaction, such as gas price or nonce. * @returns {Promise} A promise that resolves to the unsigned transaction that can be used to create the strategies. */ - public async batchCreateStrategies( + public async routerCreateStrategies( strategies: BatchCreateBuySellStrategy[], gradientStrategies: BatchCreateGradientStrategy[], overrides?: PayableOverrides ): Promise { - logger.debug('batchCreateStrategies called', arguments); + logger.debug('routerCreateStrategies called', arguments); const decimals = this._decimals; const encStrategies = await Promise.all( @@ -1493,7 +1493,7 @@ export class Toolkit { }) ); - logger.debug('batchCreateStrategies info:', { + logger.debug('routerCreateStrategies info:', { encStrategies, encGradientStrategies, }); From 2303f04321706331452652b859df0939ce0cb4ba Mon Sep 17 00:00:00 2001 From: Grandschtroumpf Date: Fri, 5 Jun 2026 15:49:13 +0200 Subject: [PATCH 7/8] fix tests --- tests/toolkit.spec.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/toolkit.spec.ts b/tests/toolkit.spec.ts index 2446c49..58fa45d 100644 --- a/tests/toolkit.spec.ts +++ b/tests/toolkit.spec.ts @@ -166,7 +166,7 @@ describe('Toolkit', () => { composer: { updateStrategy: sinon.stub(), createStrategy: sinon.stub(), - batchCreateStrategies: sinon.stub(), + routerCreateStrategies: sinon.stub(), }, }; cacheMock = sinon.createStubInstance(ChainCache); @@ -1024,7 +1024,7 @@ describe('Toolkit', () => { }); }); - describe('batchCreateStrategies', () => { + describe('routerCreateStrategies', () => { const regularStrategies = [ { baseToken: 'baseA', @@ -1071,14 +1071,14 @@ describe('Toolkit', () => { }, ]; - it('should encode regular and gradient strategies and pass them to composer.batchCreateStrategies', async () => { + it('should encode regular and gradient strategies and pass them to composer.routerCreateStrategies', async () => { const toolkit = new Toolkit(apiMock, cacheMock, decimalFetcher); - await toolkit.batchCreateStrategies( + await toolkit.routerCreateStrategies( regularStrategies, gradientStrategies ); - const args = apiMock.composer.batchCreateStrategies.getCall(0).args; + const args = apiMock.composer.routerCreateStrategies.getCall(0).args; const expectedRegular = regularStrategies.map((s) => { const encStrategy = encodeStrategy( buildStrategyObject( @@ -1142,13 +1142,13 @@ describe('Toolkit', () => { it('should pass overrides through as the third argument', async () => { const overrides = { gasLimit: 123456n }; const toolkit = new Toolkit(apiMock, cacheMock, decimalFetcher); - await toolkit.batchCreateStrategies( + await toolkit.routerCreateStrategies( regularStrategies, gradientStrategies, overrides ); - const args = apiMock.composer.batchCreateStrategies.getCall(0).args; + const args = apiMock.composer.routerCreateStrategies.getCall(0).args; expect(args[2]).to.deep.equal(overrides); }); }); From a8d96e5af335b09ca1eec7317bc1e8340876098e Mon Sep 17 00:00:00 2001 From: Doron Zavelevsky Date: Fri, 5 Jun 2026 17:42:30 +0100 Subject: [PATCH 8/8] ABI and version --- package.json | 2 +- src/abis/CarbonRouter.json | 1033 ++++++++++++++++++++++++------------ 2 files changed, 708 insertions(+), 327 deletions(-) diff --git a/package.json b/package.json index 460329c..e6bfa43 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "@bancor/carbon-sdk", "type": "module", "source": "src/index.ts", - "version": "0.0.138-DEV", + "version": "0.0.139-DEV", "description": "The SDK is a READ-ONLY tool, intended to facilitate working with Carbon contracts. It's a convenient wrapper around our matching algorithm, allowing programs and users get a ready to use transaction data that will allow them to manage strategies and fulfill trades", "main": "dist/index.cjs", "module": "dist/index.js", diff --git a/src/abis/CarbonRouter.json b/src/abis/CarbonRouter.json index 4545d00..0a7e1d5 100644 --- a/src/abis/CarbonRouter.json +++ b/src/abis/CarbonRouter.json @@ -2,483 +2,864 @@ "address": "0x654a1a16f10d73567920ad803c54e03b0f4c6c81", "abi": [ { - "type": "constructor", - "name": "", - "stateMutability": "", - "constant": false, + "anonymous": false, "inputs": [ { - "type": "address", - "name": "carbonVoucherInit", - "simpleType": "address" + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" }, { - "type": "address", - "name": "gradientVoucherInit", - "simpleType": "address" + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" } ], - "id": "e4ba6aa4-752c-48ad-ae1f-d2c7329d4400" + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" }, { - "type": "function", - "name": "initialize", - "stateMutability": "nonpayable", - "constant": false, "inputs": [], - "outputs": [], - "id": "0x8129fc1c" + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" }, { - "type": "function", - "name": "postUpgrade", + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], "stateMutability": "nonpayable", - "constant": false, + "type": "function" + }, + { "inputs": [ - { "type": "bool", "name": "checkVersion", "simpleType": "bool" }, - { "type": "bytes", "name": "data", "simpleType": "bytes" } + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } ], + "name": "upgradeTo", "outputs": [], - "id": "0xdebcf1fe" + "stateMutability": "nonpayable", + "type": "function" }, { - "type": "function", - "name": "revokeRole", - "stateMutability": "nonpayable", - "constant": false, "inputs": [ - { "type": "bytes32", "name": "role", "simpleType": "bytes" }, - { "type": "address", "name": "account", "simpleType": "address" } + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } ], + "name": "upgradeToAndCall", "outputs": [], - "id": "0xd547741f" + "stateMutability": "payable", + "type": "function" }, { - "type": "function", - "name": "getRoleMemberCount", - "stateMutability": "view", - "constant": false, - "inputs": [{ "type": "bytes32", "name": "role", "simpleType": "bytes" }], - "outputs": [{ "type": "uint256", "name": "", "simpleType": "uint" }], - "id": "0xca15c873" + "stateMutability": "payable", + "type": "receive" }, { - "type": "function", - "name": "getRoleMember", - "stateMutability": "view", - "constant": false, - "inputs": [ - { "type": "bytes32", "name": "role", "simpleType": "bytes" }, - { "type": "uint256", "name": "index", "simpleType": "uint" } - ], - "outputs": [{ "type": "address", "name": "", "simpleType": "address" }], - "id": "0x9010d07c" + "inputs": [], + "name": "AccessDenied", + "type": "error" }, { - "type": "function", - "name": "onERC721Received", - "stateMutability": "pure", - "constant": false, - "inputs": [ - { "type": "address", "name": "", "simpleType": "address" }, - { "type": "address", "name": "", "simpleType": "address" }, - { "type": "uint256", "name": "", "simpleType": "uint" }, - { "type": "bytes", "name": "", "simpleType": "bytes" } - ], - "outputs": [{ "type": "bytes4", "name": "", "simpleType": "bytes" }], - "id": "0x150b7a02" + "inputs": [], + "name": "AlreadyInitialized", + "type": "error" }, { - "type": "function", - "name": "version", - "stateMutability": "pure", - "constant": false, "inputs": [], - "outputs": [{ "type": "uint16", "name": "", "simpleType": "uint" }], - "id": "0x54fd4d50" + "name": "InsufficientNativeTokenSent", + "type": "error" }, { - "type": "function", - "name": "batchTradeByTargetAmount", - "stateMutability": "payable", - "constant": false, + "inputs": [], + "name": "InvalidAddress", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidControllerType", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroValue", + "type": "error" + }, + { + "anonymous": false, "inputs": [ { - "type": "tuple[]", - "name": "trades", - "simpleType": "slice", - "nestedType": { "type": "tuple" }, - "components": [ - { - "type": "address", - "name": "sourceToken", - "simpleType": "address" - }, - { - "type": "address", - "name": "targetToken", - "simpleType": "address" - }, - { - "type": "tuple[]", - "name": "tradeActions", - "simpleType": "slice", - "nestedType": { "type": "tuple" }, - "components": [ - { - "type": "uint256", - "name": "strategyId", - "simpleType": "uint" - }, - { "type": "uint128", "name": "amount", "simpleType": "uint" } - ] - }, - { "type": "uint256", "name": "deadline", "simpleType": "uint" }, - { "type": "uint128", "name": "maxInput", "simpleType": "uint" }, - { "type": "uint16", "name": "controllerType", "simpleType": "uint" } - ] + "indexed": true, + "internalType": "Token", + "name": "token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" } ], - "outputs": [], - "id": "0x89562094" + "name": "FundsWithdrawn", + "type": "event" }, { - "type": "function", - "name": "roleAdmin", - "stateMutability": "pure", - "constant": false, - "inputs": [], - "outputs": [{ "type": "bytes32", "name": "", "simpleType": "bytes" }], - "id": "0x93867fb5" + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" }, { - "type": "function", - "name": "grantRole", - "stateMutability": "nonpayable", - "constant": false, + "anonymous": false, "inputs": [ - { "type": "bytes32", "name": "role", "simpleType": "bytes" }, - { "type": "address", "name": "account", "simpleType": "address" } + { + "indexed": true, + "internalType": "uint16", + "name": "controllerType", + "type": "uint16" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "target", + "type": "address" + } ], - "outputs": [], - "id": "0x2f2ff15d" + "name": "NFTWithdrawn", + "type": "event" }, { - "type": "function", - "name": "supportsInterface", - "stateMutability": "view", - "constant": false, + "anonymous": false, "inputs": [ - { "type": "bytes4", "name": "interfaceId", "simpleType": "bytes" } + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } ], - "outputs": [{ "type": "bool", "name": "", "simpleType": "bool" }], - "id": "0x01ffc9a7" + "name": "RoleAdminChanged", + "type": "event" }, { - "type": "function", - "name": "DEFAULT_ADMIN_ROLE", - "stateMutability": "view", - "constant": false, - "inputs": [], - "outputs": [{ "type": "bytes32", "name": "", "simpleType": "bytes" }], - "id": "0xa217fddf" + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" }, { - "type": "function", - "name": "getRoleAdmin", - "stateMutability": "view", - "constant": false, - "inputs": [{ "type": "bytes32", "name": "role", "simpleType": "bytes" }], - "outputs": [{ "type": "bytes32", "name": "", "simpleType": "bytes" }], - "id": "0x248a9ca3" + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" }, { - "type": "function", - "name": "batchTradeBySourceAmount", - "stateMutability": "payable", - "constant": false, + "anonymous": false, "inputs": [ { - "type": "tuple[]", - "name": "trades", - "simpleType": "slice", - "nestedType": { "type": "tuple" }, - "components": [ - { - "type": "address", - "name": "sourceToken", - "simpleType": "address" - }, - { - "type": "address", - "name": "targetToken", - "simpleType": "address" - }, - { - "type": "tuple[]", - "name": "tradeActions", - "simpleType": "slice", - "nestedType": { "type": "tuple" }, - "components": [ - { - "type": "uint256", - "name": "strategyId", - "simpleType": "uint" - }, - { "type": "uint128", "name": "amount", "simpleType": "uint" } - ] - }, - { "type": "uint256", "name": "deadline", "simpleType": "uint" }, - { "type": "uint128", "name": "minReturn", "simpleType": "uint" }, - { "type": "uint16", "name": "controllerType", "simpleType": "uint" } - ] + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "strategyIds", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "gradientStrategyIds", + "type": "uint256[]" } ], - "outputs": [], - "id": "0xd63b3b8a" + "name": "StrategiesCreated", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" }, { - "type": "function", - "name": "batchCreate", - "stateMutability": "payable", - "constant": false, "inputs": [ { - "type": "tuple[]", - "name": "strategies", - "simpleType": "slice", - "nestedType": { "type": "tuple" }, "components": [ { - "type": "address[2]", + "internalType": "Token[2]", "name": "tokens", - "simpleType": "array", - "nestedType": { "type": "address" } + "type": "address[2]" }, { - "type": "tuple[2]", - "name": "orders", - "simpleType": "array", - "nestedType": { "type": "tuple" }, "components": [ - { "type": "uint128", "name": "y", "simpleType": "uint" }, - { "type": "uint128", "name": "z", "simpleType": "uint" }, - { "type": "uint64", "name": "A", "simpleType": "uint" }, - { "type": "uint64", "name": "B", "simpleType": "uint" } - ] + { + "internalType": "uint128", + "name": "y", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "z", + "type": "uint128" + }, + { + "internalType": "uint64", + "name": "A", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "B", + "type": "uint64" + } + ], + "internalType": "struct Order[2]", + "name": "orders", + "type": "tuple[2]" } - ] + ], + "internalType": "struct StrategyData[]", + "name": "strategies", + "type": "tuple[]" }, { - "type": "tuple[]", - "name": "gradientStrategies", - "simpleType": "slice", - "nestedType": { "type": "tuple" }, "components": [ { - "type": "address[2]", + "internalType": "Token[2]", "name": "tokens", - "simpleType": "array", - "nestedType": { "type": "address" } + "type": "address[2]" }, { - "type": "tuple[2]", - "name": "orders", - "simpleType": "array", - "nestedType": { "type": "tuple" }, "components": [ { - "type": "uint128", + "internalType": "uint128", "name": "liquidity", - "simpleType": "uint" + "type": "uint128" }, { - "type": "uint64", + "internalType": "uint64", "name": "initialPrice", - "simpleType": "uint" + "type": "uint64" }, { - "type": "uint32", + "internalType": "uint32", "name": "tradingStartTime", - "simpleType": "uint" + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "expiry", + "type": "uint32" }, - { "type": "uint32", "name": "expiry", "simpleType": "uint" }, { - "type": "uint32", + "internalType": "uint32", "name": "multiFactor", - "simpleType": "uint" + "type": "uint32" }, { - "type": "uint8", + "internalType": "enum GradientType", "name": "gradientType", - "simpleType": "uint" + "type": "uint8" } - ] + ], + "internalType": "struct GradientOrder[2]", + "name": "orders", + "type": "tuple[2]" } - ] + ], + "internalType": "struct GradientStrategyData[]", + "name": "gradientStrategies", + "type": "tuple[]" } ], + "name": "batchCreate", "outputs": [ { - "type": "uint256[]", + "internalType": "uint256[]", "name": "", - "simpleType": "slice", - "nestedType": { "type": "uint", "count": 256 } + "type": "uint256[]" }, { - "type": "uint256[]", + "internalType": "uint256[]", "name": "", - "simpleType": "slice", - "nestedType": { "type": "uint", "count": 256 } + "type": "uint256[]" } ], - "id": "0x144ea82e" + "stateMutability": "payable", + "type": "function" }, { - "type": "function", - "name": "hasRole", - "stateMutability": "view", - "constant": false, "inputs": [ - { "type": "bytes32", "name": "role", "simpleType": "bytes" }, - { "type": "address", "name": "account", "simpleType": "address" } + { + "components": [ + { + "internalType": "Token", + "name": "sourceToken", + "type": "address" + }, + { + "internalType": "Token", + "name": "targetToken", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "strategyId", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "amount", + "type": "uint128" + } + ], + "internalType": "struct TradeAction[]", + "name": "tradeActions", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "minReturn", + "type": "uint128" + }, + { + "internalType": "uint16", + "name": "controllerType", + "type": "uint16" + } + ], + "internalType": "struct TradeBySourceAmountData[]", + "name": "trades", + "type": "tuple[]" + } ], - "outputs": [{ "type": "bool", "name": "", "simpleType": "bool" }], - "id": "0x91d14854" + "name": "batchTradeBySourceAmount", + "outputs": [], + "stateMutability": "payable", + "type": "function" }, { - "type": "function", - "name": "renounceRole", - "stateMutability": "nonpayable", - "constant": false, "inputs": [ - { "type": "bytes32", "name": "role", "simpleType": "bytes" }, - { "type": "address", "name": "account", "simpleType": "address" } + { + "components": [ + { + "internalType": "Token", + "name": "sourceToken", + "type": "address" + }, + { + "internalType": "Token", + "name": "targetToken", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "strategyId", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "amount", + "type": "uint128" + } + ], + "internalType": "struct TradeAction[]", + "name": "tradeActions", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "deadline", + "type": "uint256" + }, + { + "internalType": "uint128", + "name": "maxInput", + "type": "uint128" + }, + { + "internalType": "uint16", + "name": "controllerType", + "type": "uint16" + } + ], + "internalType": "struct TradeByTargetAmountData[]", + "name": "trades", + "type": "tuple[]" + } ], + "name": "batchTradeByTargetAmount", "outputs": [], - "id": "0x36568abe" + "stateMutability": "payable", + "type": "function" }, { - "type": "function", - "name": "withdrawFunds", - "stateMutability": "nonpayable", - "constant": false, "inputs": [ - { "type": "address", "name": "token", "simpleType": "address" }, - { "type": "address", "name": "target", "simpleType": "address" }, - { "type": "uint256", "name": "amount", "simpleType": "uint" } + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } ], - "outputs": [], - "id": "0x1c20fadd" + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" }, { - "type": "function", - "name": "withdrawNFT", + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getRoleMember", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleMemberCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], "stateMutability": "nonpayable", - "constant": false, + "type": "function" + }, + { "inputs": [ - { "type": "uint16", "name": "controllerType", "simpleType": "uint" }, - { "type": "uint256", "name": "tokenId", "simpleType": "uint" }, - { "type": "address", "name": "target", "simpleType": "address" } + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", "outputs": [], - "id": "0xf365bc8a" + "stateMutability": "nonpayable", + "type": "function" }, { - "type": "event", - "name": "RoleGranted", - "stateMutability": "", - "constant": false, "inputs": [ - { "type": "bytes32", "name": "role", "simpleType": "bytes" }, - { "type": "address", "name": "account", "simpleType": "address" }, - { "type": "address", "name": "sender", "simpleType": "address" } + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } ], - "id": "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d" + "name": "onERC721Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "pure", + "type": "function" }, { - "type": "event", - "name": "RoleRevoked", - "stateMutability": "", - "constant": false, "inputs": [ - { "type": "bytes32", "name": "role", "simpleType": "bytes" }, - { "type": "address", "name": "account", "simpleType": "address" }, - { "type": "address", "name": "sender", "simpleType": "address" } + { + "internalType": "bool", + "name": "checkVersion", + "type": "bool" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } ], - "id": "0xf6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b" + "name": "postUpgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "type": "event", - "name": "StrategiesCreated", - "stateMutability": "", - "constant": false, "inputs": [ - { "type": "address", "name": "owner", "simpleType": "address" }, { - "type": "uint256[]", - "name": "strategyIds", - "simpleType": "slice", - "nestedType": { "type": "uint", "count": 256 } + "internalType": "bytes32", + "name": "role", + "type": "bytes32" }, { - "type": "uint256[]", - "name": "gradientStrategyIds", - "simpleType": "slice", - "nestedType": { "type": "uint", "count": 256 } + "internalType": "address", + "name": "account", + "type": "address" } ], - "id": "0xf420980ae6459276d91c7e51a10c1e6bf711628543fea7ee7c0ab260aa7fb6e8" + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "type": "event", - "name": "FundsWithdrawn", - "stateMutability": "", - "constant": false, "inputs": [ - { "type": "address", "name": "token", "simpleType": "address" }, - { "type": "address", "name": "caller", "simpleType": "address" }, - { "type": "address", "name": "target", "simpleType": "address" }, - { "type": "uint256", "name": "amount", "simpleType": "uint" } + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } ], - "id": "0xc322efa58c9cb2c39cfffdac61d35c8643f5cbf13c6a7d0034de2cf18923aff3" + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "type": "event", - "name": "Initialized", - "stateMutability": "", - "constant": false, - "inputs": [{ "type": "uint8", "name": "version", "simpleType": "uint" }], - "id": "0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498" + "inputs": [], + "name": "roleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" }, { - "type": "event", - "name": "NFTWithdrawn", - "stateMutability": "", - "constant": false, "inputs": [ - { "type": "uint16", "name": "controllerType", "simpleType": "uint" }, - { "type": "uint256", "name": "tokenId", "simpleType": "uint" }, - { "type": "address", "name": "caller", "simpleType": "address" }, - { "type": "address", "name": "target", "simpleType": "address" } + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } ], - "id": "0x0fd532ac4d780682db2e44d81e24740f2e15526d3c7d385b3b4f447ef3cbee7f" + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "pure", + "type": "function" }, { - "type": "event", - "name": "RoleAdminChanged", - "stateMutability": "", - "constant": false, "inputs": [ - { "type": "bytes32", "name": "role", "simpleType": "bytes" }, { - "type": "bytes32", - "name": "previousAdminRole", - "simpleType": "bytes" + "internalType": "Token", + "name": "token", + "type": "address" + }, + { + "internalType": "address payable", + "name": "target", + "type": "address" }, - { "type": "bytes32", "name": "newAdminRole", "simpleType": "bytes" } + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } ], - "id": "0xbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff" + "name": "withdrawFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "controllerType", + "type": "uint16" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "target", + "type": "address" + } + ], + "name": "withdrawNFT", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" } ] }