Skip to content

Commit

Permalink
Flag "echo" transfers as imitations (#2026)
Browse files Browse the repository at this point in the history
Adds new logic to flag "echo" transactions. If the receipt of a token occurs after it being sent, under a defined limit, it is deemed an "echo" and flagges as such:

- Add `mappings.imitation.echoLimit` value
- Flag "echo" transactions
- Add appropriate test coverage
  • Loading branch information
iamacook authored Oct 23, 2024
1 parent d1df7ae commit c3fc573
Show file tree
Hide file tree
Showing 4 changed files with 1,425 additions and 7 deletions.
3 changes: 2 additions & 1 deletion src/config/entities/__tests__/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,10 @@ export default (): ReturnType<typeof configuration> => ({
mappings: {
imitation: {
lookupDistance: faker.number.int(),
valueTolerance: faker.number.bigInt(),
prefixLength: faker.number.int(),
suffixLength: faker.number.int(),
valueTolerance: faker.number.bigInt(),
echoLimit: faker.number.bigInt(),
},
history: {
maxNestedTransfers: faker.number.int({ min: 1, max: 5 }),
Expand Down
5 changes: 3 additions & 2 deletions src/config/entities/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -259,11 +259,12 @@ export default () => ({
mappings: {
imitation: {
lookupDistance: parseInt(process.env.IMITATION_LOOKUP_DISTANCE ?? `${3}`),
prefixLength: parseInt(process.env.IMITATION_PREFIX_LENGTH ?? `${3}`),
suffixLength: parseInt(process.env.IMITATION_SUFFIX_LENGTH ?? `${4}`),
// Note: due to high value formatted token values, we use bigint
// This means the value tolerance can only be an integer
valueTolerance: BigInt(process.env.IMITATION_VALUE_TOLERANCE ?? 1),
prefixLength: parseInt(process.env.IMITATION_PREFIX_LENGTH ?? `${3}`),
suffixLength: parseInt(process.env.IMITATION_SUFFIX_LENGTH ?? `${4}`),
echoLimit: BigInt(process.env.IMITATION_ECHO_LIMIT ?? `${10}`),
},
history: {
maxNestedTransfers: parseInt(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export class TransferImitationMapper {
private readonly prefixLength: number;
private readonly suffixLength: number;
private readonly valueTolerance: bigint;
private readonly echoLimit: bigint;

constructor(
@Inject(IConfigurationService)
Expand All @@ -44,6 +45,9 @@ export class TransferImitationMapper {
this.valueTolerance = configurationService.getOrThrow(
'mappings.imitation.valueTolerance',
);
this.echoLimit = configurationService.getOrThrow(
'mappings.imitation.echoLimit',
);
}

/**
Expand Down Expand Up @@ -113,7 +117,10 @@ export class TransferImitationMapper {
return false;
}

return this.isSpoofedEvent(txInfo, prevTxInfo);
return (
this.isSpoofedEvent(txInfo, prevTxInfo) ||
this.isEchoImitation(txInfo, prevTxInfo)
);
});

txInfo.transferInfo.imitation = isImitation;
Expand Down Expand Up @@ -155,6 +162,38 @@ export class TransferImitationMapper {
return this.isImitatorAddress(refAddress, prevRefAddress);
}

/**
* Returns whether {@link txInfo} is incoming transfer imitating {@link prevTxInfo}
*
* A low-value (below a defined threshold) incoming transfer of the same token
* previously sent is deemed an imitation.
*
* @param {Erc20TransferTransactionInfo} txInfo - transaction info to compare
* @param {Erc20TransferTransactionInfo} prevTxInfo - previous transaction info
* @returns {boolean} - whether the transaction is an imitation
*/
isEchoImitation(
txInfo: Erc20TransferTransactionInfo,
prevTxInfo: Erc20TransferTransactionInfo,
): boolean {
// Incoming transfer imitations must be of the same token
const isSameToken =
txInfo.transferInfo.tokenAddress === txInfo.transferInfo.tokenAddress;
const isIncoming = txInfo.direction === TransferDirection.Incoming;
const isPrevOutgoing = prevTxInfo.direction === TransferDirection.Outgoing;
if (!isSameToken || !isIncoming || !isPrevOutgoing) {
return false;
}

// Is imitation if value is lower than the specified threshold
const value = this.formatValue(txInfo.transferInfo);
const prevValue = this.formatValue(prevTxInfo.transferInfo);
return (
// Imitations generally follow high transfer values
prevValue >= this.echoLimit && value <= this.echoLimit
);
}

/**
* Returns whether the transaction info is an ERC-20 transfer
* @param {Erc20TransferTransactionInfo} txInfo - transaction info
Expand Down
Loading

0 comments on commit c3fc573

Please sign in to comment.