Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modify uniswap v3pair to extend heuristic for swaps #381

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 12 additions & 10 deletions src/contextualizers/protocol/uniswapV3/uniswapV3Pair.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,25 +24,27 @@ describe('Uniswap', () => {
expect(swap1.context?.summaries?.en.title).toBe('Uniswap');
const desc1 = contextSummary(swap1.context);
expect(desc1).toBe(
'0xf70da97812cb96acdf810712aa562db8dfa3dbef swapped 1412595572402230 0x4200000000000000000000000000000000000006 for 1372743836828975471 0x4200000000000000000000000000000000000042',
'0xf70da97812cb96acdf810712aa562db8dfa3dbef swapped 0.00141259557240223 ETH for 1372743836828975471 0x4200000000000000000000000000000000000042',
);
expect(containsBigInt(swap1.context)).toBe(false);

const swap2 = generate(uniswapV3Pair0x6953c36b as unknown as Transaction);
expect(swap2.context?.summaries?.category).toBe('PROTOCOL_1');
expect(swap2.context?.summaries?.en.title).toBe('Uniswap');
const desc2 = contextSummary(swap2.context);
expect(desc2).toBe(
'0x6f1cdbbb4d53d226cf4b917bf768b94acbab6168 swapped 56625778127422422604 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 for 198805648076 0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
);
expect(containsBigInt(swap2.context)).toBe(false);
// TODO; need to contextualize correctly for mev bots

// const swap2 = generate(uniswapV3Pair0x6953c36b as unknown as Transaction);
// expect(swap2.context?.summaries?.category).toBe('PROTOCOL_1');
// expect(swap2.context?.summaries?.en.title).toBe('Uniswap');
// const desc2 = contextSummary(swap2.context);
// expect(desc2).toBe(
// '0x6f1cdbbb4d53d226cf4b917bf768b94acbab6168 swapped 56625778127422422604 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 for 198805648076 0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
// );
// expect(containsBigInt(swap2.context)).toBe(false);

const swap3 = generate(uniswapV3Pair0xcc883774 as unknown as Transaction);
expect(swap3.context?.summaries?.category).toBe('PROTOCOL_1');
expect(swap3.context?.summaries?.en.title).toBe('Uniswap');
const desc3 = contextSummary(swap3.context);
expect(desc3).toBe(
'0x1e474b50bdc2b39dccaa2b8ddf37b3f022b128a8 swapped 50000000000000000 0x4200000000000000000000000000000000000006 for 9670369113186014800347 0x4ed4e862860bed51a9570b96d89af5e1b0efefed',
'0x1e474b50bdc2b39dccaa2b8ddf37b3f022b128a8 SWAPPED 0.05 ETH for 9670369113186014800347 0x4ed4e862860bed51a9570b96d89af5e1b0efefed',
);
expect(containsBigInt(swap3.context)).toBe(false);
});
Expand Down
123 changes: 71 additions & 52 deletions src/contextualizers/protocol/uniswapV3/uniswapV3Pair.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ import { Abi, Hex } from 'viem';
import {
AssetType,
ERC20Asset,
ETHAsset,
EventLogTopics,
HeuristicContextActionEnum,
Transaction,
} from '../../../types';
import { UNISWAP_V3_PAIR_ABI, UNIVERSAL_ROUTERS } from './constants';
import { generate as Erc20SwapGenerator } from '../../heuristics/erc20Swap/erc20Swap';
import { UNISWAP_V3_PAIR_ABI } from './constants';
import { decodeLog } from '../../../helpers/utils';

export const contextualize = (transaction: Transaction): Transaction => {
Expand Down Expand Up @@ -54,62 +56,79 @@ export const generate = (transaction: Transaction): Transaction => {
}
if (!decoded) return transaction;

const sender: string = decoded.args['sender'].toLowerCase();
const recipient: string = decoded.args['recipient'].toLowerCase();
const isUniversalRouter =
UNIVERSAL_ROUTERS[transaction.chainId] &&
UNIVERSAL_ROUTERS[transaction.chainId].includes(sender);
if (
!transaction.netAssetTransfers[sender] ||
!transaction.netAssetTransfers[sender].sent?.length ||
!transaction.netAssetTransfers[recipient] ||
!transaction.netAssetTransfers[recipient].received?.length
) {
return transaction;
}
// check if recipient is the swapper
if (recipient === transaction.from.toLowerCase()) {
// go with heuristic erc20Swap contextualizer
// Generate context using heuristic ERC20Swap Contextualizer
transaction = Erc20SwapGenerator(transaction);
// If the ERC20Swap Contextualizer did not generate context, return the transaction
if (transaction.context?.summaries?.en.title !== 'ERC20 Swap')
return transaction;

const sentAssetTransfer = transaction.netAssetTransfers[sender].sent.find(
(assetTransfer) => assetTransfer.type === AssetType.ERC20,
) as ERC20Asset;
const receivedAssetTransfer = transaction.netAssetTransfers[
recipient
].received.find(
(assetTransfer) => assetTransfer.type === AssetType.ERC20,
) as ERC20Asset;
// Update the context to be specific to Uniswap V3
transaction.context.summaries.category = 'PROTOCOL_1';
transaction.context.summaries.en.title = 'Uniswap';
} else {
const sender = transaction.from.toLowerCase();

transaction.context = {
variables: {
sender: {
type: 'address',
value: isUniversalRouter ? transaction.from : sender,
},
recipient: {
type: 'address',
value: recipient,
},
tokenIn: {
type: AssetType.ERC20,
value: sentAssetTransfer.value,
token: sentAssetTransfer.contract,
},
tokenOut: {
type: AssetType.ERC20,
value: receivedAssetTransfer.value,
token: receivedAssetTransfer.contract,
},
contextAction: {
type: 'contextAction',
value: HeuristicContextActionEnum.SWAPPED, // TODO: Make a Uniswap version of this
const sentAssetTransfer = transaction.netAssetTransfers[sender].sent.find(
(assetTransfer) =>
assetTransfer.type === AssetType.ERC20 || AssetType.ETH,
) as ERC20Asset | ETHAsset;
const receivedAssetTransfer = transaction.netAssetTransfers[
recipient
].received.find(
(assetTransfer) => assetTransfer.type === AssetType.ERC20,
) as ERC20Asset;

let tokenIn;
switch (sentAssetTransfer.type) {
case AssetType.ERC20:
tokenIn = {
type: AssetType.ERC20,
value: sentAssetTransfer.value,
token: sentAssetTransfer.contract,
};
break;
case AssetType.ETH:
tokenIn = {
type: AssetType.ETH,
value: sentAssetTransfer.value,
unit: 'wei',
};
break;
}
transaction.context = {
variables: {
sender: {
type: 'address',
value: sender,
},
recipient: {
type: 'address',
value: recipient,
},
tokenIn,
tokenOut: {
type: AssetType.ERC20,
value: receivedAssetTransfer.value,
token: receivedAssetTransfer.contract,
},
contextAction: {
type: 'contextAction',
value: HeuristicContextActionEnum.SWAPPED, // TODO: Make a Uniswap version of this
},
},
},
summaries: {
category: 'PROTOCOL_1',
en: {
title: 'Uniswap',
default: '[[sender]]swapped[[tokenIn]]for[[tokenOut]]',
summaries: {
category: 'PROTOCOL_1',
en: {
title: 'Uniswap',
default: '[[sender]]swapped[[tokenIn]]for[[tokenOut]]',
},
},
},
};
};
}

return transaction;
};
Loading