Skip to content

Commit

Permalink
fix: transfers from Bootloader to an operator address (#87)
Browse files Browse the repository at this point in the history
# What ❔

Fix for transfers from Bootloader to an operator address.

## Why ❔

Not all transfers from Bootloader are _Refunds_. In blocks with no
transactions transfers from Bootloader to an operator address are
_Transfers_ and have to be saved accordingly.

## Checklist

<!-- Check your PR fulfills the following items. -->
<!-- For draft PRs check the boxes as you complete them. -->

- [X] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [X] Tests for the changes have been added / updated.
  • Loading branch information
vasyl-ivanchuk authored Nov 14, 2023
1 parent 2e252da commit c080938
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 4 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ tests/e2e/artifacts/

# Logs
logs
!/packages/worker/test/logs/
*.log
npm-debug.log*
yarn-debug.log*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { MigrationInterface, QueryRunner } from "typeorm";

export class SetTransferTypeForEmptyBlockTransfers1699955766418 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`
WITH "updatedTransferNumbers" AS
(
UPDATE transfers
SET "type" = 'transfer', "isFeeOrRefund" = false, "isInternal" = true
WHERE "transactionHash" IS NULL
RETURNING number
)
UPDATE "addressTransfers"
SET "isFeeOrRefund" = false, "isInternal" = true
FROM "updatedTransferNumbers"
WHERE "transferNumber" = "updatedTransferNumbers"."number"
`);
}

// eslint-disable-next-line @typescript-eslint/no-empty-function
public async down(): Promise<void> {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -123,18 +123,32 @@ describe("defaultTransferHandler", () => {
expect(result.isFeeOrRefund).toBe(true);
});

it("extracts transfer of refund type if from address is a bootloader address", () => {
it("extracts transfer of refund type if from address is a bootloader address and there are transaction details", () => {
const transactionDetails = mock<types.TransactionDetails>();
log.topics[1] = "0x0000000000000000000000000000000000000000000000000000000000008001";
const result = defaultTransferHandler.extract(log, blockDetails);
const result = defaultTransferHandler.extract(log, blockDetails, transactionDetails);
expect(result.type).toBe(TransferType.Refund);
});

it("adds isFeeOrRefund as true if from address is a bootloader address", () => {
it("extracts transfer of transfer type if from address is a bootloader address and there are no transaction details", () => {
log.topics[1] = "0x0000000000000000000000000000000000000000000000000000000000008001";
const result = defaultTransferHandler.extract(log, blockDetails);
expect(result.type).toBe(TransferType.Transfer);
});

it("adds isFeeOrRefund as true if from address is a bootloader address and there are transaction details", () => {
const transactionDetails = mock<types.TransactionDetails>();
log.topics[1] = "0x0000000000000000000000000000000000000000000000000000000000008001";
const result = defaultTransferHandler.extract(log, blockDetails, transactionDetails);
expect(result.isFeeOrRefund).toBe(true);
});

it("adds isFeeOrRefund as false if from address is a bootloader address and there are no transaction details", () => {
log.topics[1] = "0x0000000000000000000000000000000000000000000000000000000000008001";
const result = defaultTransferHandler.extract(log, blockDetails);
expect(result.isFeeOrRefund).toBe(false);
});

it("extracts transfer of transfer type if neither to address nor from address is a bootload address", () => {
const result = defaultTransferHandler.extract(log, blockDetails);
expect(result.type).toBe(TransferType.Transfer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ export const defaultTransferHandler: ExtractTransferHandler = {
let transferType: TransferType = TransferType.Transfer;
if (parsedLog.args.to === utils.BOOTLOADER_FORMAL_ADDRESS) {
transferType = TransferType.Fee;
} else if (parsedLog.args.from === utils.BOOTLOADER_FORMAL_ADDRESS) {
}
// if transactionDetails is null it means that this transfer comes from a block with
// no transactions and it is a reward to an operator address, so it's a transfer and not a refund
else if (parsedLog.args.from === utils.BOOTLOADER_FORMAL_ADDRESS && transactionDetails) {
transferType = TransferType.Refund;
}

Expand Down
31 changes: 31 additions & 0 deletions packages/worker/src/transfer/transfer.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import * as addressOutOfRange from "../../test/transactionReceipts/address-out-o
import * as logParsingError from "../../test/transactionReceipts/log-parsing-error.json";
import * as noDepositAfterFee from "../../test/transactionReceipts/no-deposit-after-fee.json";
import * as feeWithNoDeposits from "../../test/transactionReceipts/fee-with-no-deposits.json";
import * as blockWithNoTxsLogs from "../../test/logs/block-with-no-txs-logs.json";

jest.mock("../logger", () => ({
default: {
Expand Down Expand Up @@ -2285,5 +2286,35 @@ describe("TransferService", () => {
expect(result).toStrictEqual(expectedTransfers);
});
});

describe("block with no transactions", () => {
it("properly saves transfers", async () => {
const blockDate = new Date();
blockDetails.timestamp = blockDate.getTime() / 1000;

const expectedTransfers = [
{
amount: BigNumber.from("0xf22ec29c9c4980"),
blockNumber: 6711853,
from: "0x0000000000000000000000000000000000008001",
isFeeOrRefund: false,
isInternal: true,
logIndex: 0,
timestamp: blockDate,
to: "0xa9232040bf0e0aea2578a5b2243f2916dbfc0a69",
tokenAddress: "0x000000000000000000000000000000000000800a",
tokenType: "ETH",
transactionHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
transactionIndex: 0,
type: "transfer",
},
];

const result = await transferService.saveTransfers(blockWithNoTxsLogs, blockDetails);
expect(transferRepositoryMock.addMany).toHaveBeenCalledTimes(1);
expect(transferRepositoryMock.addMany).toHaveBeenCalledWith(expectedTransfers);
expect(result).toStrictEqual(expectedTransfers);
});
});
});
});
18 changes: 18 additions & 0 deletions packages/worker/test/logs/block-with-no-txs-logs.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[
{
"blockNumber": 6711853,
"blockHash": "0xe9b0940095e6e708deebd75fa0320cad868ec5029f92cf8cc8fb464314f5141e",
"transactionIndex": 0,
"removed": false,
"address": "0x000000000000000000000000000000000000800A",
"data": "0x00000000000000000000000000000000000000000000000000f22ec29c9c4980",
"topics": [
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"0x0000000000000000000000000000000000000000000000000000000000008001",
"0x000000000000000000000000a9232040bf0e0aea2578a5b2243f2916dbfc0a69"
],
"transactionHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"logIndex": 0,
"l1BatchNumber": 76725
}
]

0 comments on commit c080938

Please sign in to comment.