Skip to content

Commit

Permalink
feat: add 1inch-fusion implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
ryosevenf committed Oct 30, 2023
1 parent 1da5527 commit 824e7bf
Show file tree
Hide file tree
Showing 8 changed files with 231 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export * as blurTypes from "./blur";
export * as looksrareTypes from "./looksrare";
export * as seaportTypes from "./seaport";
export * as visualizer from "./visualizer";
export * as oneinchFusionTypes from "./oneinch-fusion";

export enum ASSET_TYPE {
NATIVE = "NATIVE",
Expand Down
15 changes: 15 additions & 0 deletions src/types/oneinch-fusion.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// see
// https://github.com/1inch/fusion-sdk/blob/4b76e9c232276742f879f3495e452dfc667b5a3a/src/limit-order/types.ts#L29-L41
// https://github.com/1inch/fusion-sdk/blob/4b76e9c232276742f879f3495e452dfc667b5a3a/src/limit-order/eip712/order-typed-data-builder.ts#L23-L37
export type OneinchFusionOrder = {
salt: string;
makerAsset: string;
takerAsset: string;
maker: string;
receiver: string;
allowedSender: string;
makingAmount: string;
takingAmount: string;
offsets: string;
interactions: string;
};
9 changes: 8 additions & 1 deletion src/visualizer/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { PermitMessage } from "../types";

import { SeaPortPayload } from "../types/seaport";
import { BlurIoOrder } from "../types/blur";
import { LooksrareMakerOrderWithEncodedParams } from "../types/looksrare";
import { OneinchFusionOrder } from "../types/oneinch-fusion";
import { SeaPortPayload } from "../types/seaport";

import blurIo from "./blur-io";
import erc20Permit from "./erc20-permit";
import looksrare from "./looksrare";
import looksrareV2 from "./looksrare-v2";
import oneinchFusion from "./oneinch-fusion";
import seaport from "./seaport";
import { Domain, VisualizationResult } from "../types/visualizer";
import { WizardError } from "../utils";
Expand All @@ -19,13 +21,15 @@ export enum PROTOCOL_ID {
LOOKSRARE_EXCHANGE_V2 = "LOOKSRARE_EXCHANGE_V2",
BLUR_IO_MARKETPLACE = "BLUR_IO_MARKETPLACE",
ERC20_PERMIT = "ERC20_PERMIT",
ONEINCH_FUSION = "ONEINCH_FUSION",
}

export const getProtocolId = (domain: Domain): PROTOCOL_ID | undefined => {
if (seaport.isCorrectDomain(domain)) return PROTOCOL_ID.OPENSEA_SEAPORT;
if (blurIo.isCorrectDomain(domain)) return PROTOCOL_ID.BLUR_IO_MARKETPLACE;
if (looksrareV2.isCorrectDomain(domain)) return PROTOCOL_ID.LOOKSRARE_EXCHANGE_V2;
if (looksrare.isCorrectDomain(domain)) return PROTOCOL_ID.LOOKSRARE_EXCHANGE;
if (oneinchFusion.isCorrectDomain(domain)) return PROTOCOL_ID.ONEINCH_FUSION;

return;
};
Expand Down Expand Up @@ -55,6 +59,9 @@ export default async function visualize<T extends object>(
case PROTOCOL_ID.BLUR_IO_MARKETPLACE:
return blurIo.visualize(message as BlurIoOrder, domain);

case PROTOCOL_ID.ONEINCH_FUSION:
return oneinchFusion.visualize(message as OneinchFusionOrder, domain);

default:
if (erc20Permit.isERC20Permit(message)) {
return erc20Permit.visualize(message as PermitMessage, domain);
Expand Down
14 changes: 14 additions & 0 deletions src/visualizer/oneinch-fusion/const.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// EIP-712 domain
export const ONEINCH_FUSION_VERIFYING_CONTRACT =
"0x1111111254eeb25477b68fb85ed929f73a960582";

export const ONEINCH_FUSION_SUPPORTED_CHAINS = [
1, //Ethereum
137, //Polygon
56, //Binance
42161, //Arbitrum One
43114, //Avalanche C-Chain
10, //Optimism
250, //Fantom
100, //Gnosis
];
28 changes: 28 additions & 0 deletions src/visualizer/oneinch-fusion/getAuctionTime.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// The bit constants refers to fusion-sdk code.
// @see https://github.com/1inch/fusion-sdk/blob/4b76e9c232276742f879f3495e452dfc667b5a3a/src/auction-salt/parser/constants.ts
const START_TIME_MASK = BigInt(
"0xFFFFFFFF00000000000000000000000000000000000000000000000000000000"
);
const DURATION_MASK = BigInt(
"0x00000000FFFFFF00000000000000000000000000000000000000000000000000"
);
const START_TIME_SHIFT = BigInt(224);
const DURATION_SHIFT = BigInt(200);

// get the auction start and end time from the salt
// see: https://github.com/1inch/fusion-sdk/blob/4b76e9c232276742f879f3495e452dfc667b5a3a/src/auction-salt/parser/parser.ts#L15-L27
export const getAuctionTime = (salt: string): { startTime: number; endTime: number } => {
const startTime = getAuctionStartTime(salt);
const duration = getAuctionDuration(salt);

return {
startTime: Number(startTime),
endTime: Number(startTime + duration),
};
};

const getAuctionStartTime = (salt: string) =>
(BigInt(salt) & START_TIME_MASK) >> START_TIME_SHIFT;

const getAuctionDuration = (salt: string) =>
(BigInt(salt) & DURATION_MASK) >> DURATION_SHIFT;
79 changes: 79 additions & 0 deletions src/visualizer/oneinch-fusion/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { Domain, EIP712Protocol, VisualizationResult } from "../../types/visualizer";
import { OneinchFusionOrder } from "../../types/oneinch-fusion";
import { PROTOCOL_ID } from "..";
import { ASSET_TYPE, AssetInOut } from "../../types";
import { ZERO_ADDRESS, getPaymentAssetType } from "../../utils";
import { getAuctionTime } from "./getAuctionTime";

const { NATIVE } = ASSET_TYPE;

// @see https://github.com/1inch/fusion-sdk/blob/4b76e9c232276742f879f3495e452dfc667b5a3a/src/constants.ts#L50
export const ONEINCH_FUSION_VERIFYING_CONTRACT =
"0x1111111254eeb25477b68fb85ed929f73a960582";

// @see https://github.com/1inch/fusion-sdk/blob/4b76e9c232276742f879f3495e452dfc667b5a3a/src/constants.ts#L6-L15
export const ONEINCH_FUSION_SUPPORTED_CHAINS = [
1, //Ethereum
137, //Polygon
56, //Binance
42161, //Arbitrum One
43114, //Avalanche C-Chain
10, //Optimism
250, //Fantom
100, //Gnosis
];

export const isCorrectDomain = (domain: Domain) => {
return (
ONEINCH_FUSION_SUPPORTED_CHAINS.includes(Number(domain.chainId)) &&
addressesBook.includes(domain.verifyingContract.toLocaleLowerCase())
);
};

export const visualize = (
message: OneinchFusionOrder,
domain: Domain
): VisualizationResult => {
if (!isCorrectDomain(domain)) throw new Error("wrong 1inch-fusion domain");

const makerAssetType = getPaymentAssetType(message.makerAsset);
const assetsIn: AssetInOut[] = [
{
address: makerAssetType === NATIVE ? ZERO_ADDRESS : message.makerAsset,
type: makerAssetType,
amounts: [message.makingAmount],
},
];

const takerAssetType = getPaymentAssetType(message.takerAsset);
const assetsOut: AssetInOut[] = [
{
address: takerAssetType === NATIVE ? ZERO_ADDRESS : message.takerAsset,
type: takerAssetType,
amounts: [message.takingAmount],
},
];

const { startTime, endTime } = getAuctionTime(message.salt);

return {
protocol: PROTOCOL_ID.ONEINCH_FUSION,
assetsIn,
assetsOut,
liveness: {
from: startTime,
to: endTime,
},
approvals: [],
};
};

const addressesBook = [ONEINCH_FUSION_VERIFYING_CONTRACT].map((e) =>
e.toLocaleLowerCase()
);

const oneinchFusion: EIP712Protocol<OneinchFusionOrder> = {
isCorrectDomain,
visualize,
};
export default oneinchFusion;
21 changes: 21 additions & 0 deletions test/visualizer/oneinch-fusion/data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { oneinchFusionTypes } from "../../../src/types";

// Test data refers to fusion-sdk code.
// https://github.com/1inch/fusion-sdk/blob/4b76e9c232276742f879f3495e452dfc667b5a3a/src/fusion-order/fusion-order.spec.ts#L12-L61

const oneinchFusionOrder: oneinchFusionTypes.OneinchFusionOrder = {
salt: "45118768841948961586167738353692277076075522015101619148498725069326976558864",
makerAsset: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
takerAsset: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
maker: "0x00000000219ab540356cbb839cbe05303d7705fa",
receiver: "0x0000000000000000000000000000000000000000",
allowedSender: "0xa88800cd213da5ae406ce248380802bd53b47647",
makingAmount: "1000000000000000000",
takingAmount: "1420000000",
offsets: "0",
interactions: "0x000c004e200000000000000000219ab540356cbb839cbe05303d7705faf486570009",
};

Object.freeze(oneinchFusionOrder);

export { oneinchFusionOrder };
65 changes: 65 additions & 0 deletions test/visualizer/oneinch-fusion/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { Domain } from "../../../src/types/visualizer";
import visualize from "../../../src/visualizer";
import oneinchFusion from "../../../src/visualizer/oneinch-fusion";

import { oneinchFusionOrder } from "./data";

describe("oneinch-fusion", () => {
const oneinchFusionDomain: Domain = {
chainId: "1",
name: "1inch Aggregation Router",
verifyingContract: "0x1111111254eeb25477b68fb85ed929f73a960582",
version: "5",
};

it("should revert if domain is not recognized by SDK entry", async () => {
await expect(
visualize(oneinchFusionOrder, { ...oneinchFusionDomain, chainId: "-1" })
).rejects.toThrowError("Unrecognized/Unsupported EIP712Protocol Domain");
});

it("should revert at oneinch-fusion module level if the domain verifyingContract is wrong", () => {
expect(() => {
oneinchFusion.visualize(oneinchFusionOrder, {
...oneinchFusionDomain,
verifyingContract: "0x0",
});
}).toThrow("wrong 1inch-fusion domain");
});

it("should revert at oneinch-fusion module level if the domain chainId is wrong", () => {
expect(() => {
oneinchFusion.visualize(oneinchFusionOrder, {
...oneinchFusionDomain,
chainId: "-1",
});
}).toThrow("wrong 1inch-fusion domain");
});

it("should successfully visualize oneinch-fusion order", async () => {
const result = await visualize(oneinchFusionOrder, oneinchFusionDomain);

expect(result).toEqual({
protocol: "ONEINCH_FUSION",
assetsIn: [
{
address: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
amounts: ["1000000000000000000"],
type: "ERC20",
},
],
assetsOut: [
{
address: "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
amounts: ["1420000000"],
type: "ERC20",
},
],
liveness: {
from: 1673548149,
to: 1673548329,
},
approvals: [],
});
});
});

0 comments on commit 824e7bf

Please sign in to comment.