Skip to content

Commit

Permalink
test: Add test cases for ERC-721 deposit.
Browse files Browse the repository at this point in the history
  • Loading branch information
brunomenezes committed Dec 12, 2023
1 parent e66d173 commit 94d6846
Show file tree
Hide file tree
Showing 2 changed files with 183 additions and 7 deletions.
141 changes: 135 additions & 6 deletions tests/handlers/InputAdded.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,18 @@
import { dataSlice, getUint } from 'ethers';
import { beforeEach, describe, expect, test, vi } from 'vitest';
import { afterEach } from 'node:test';
import { MockedObject, beforeEach, describe, expect, test, vi } from 'vitest';
import { Contract } from '../../src/abi/ERC20';
import { Contract as ERC721 } from '../../src/abi/ERC721';
import InputAdded from '../../src/handlers/InputAdded';
import { Application, Erc20Deposit, Token } from '../../src/model';
import { block, ctx, input, logs } from '../stubs/params';
import {
Application,
Erc20Deposit,
Erc721Deposit,
Input,
NFT,
Token,
} from '../../src/model';
import { block, ctx, input, logErc721Transfer, logs } from '../stubs/params';

vi.mock('../../src/abi/ERC20', async (importOriginal) => {
const actualMods = await importOriginal;
Expand All @@ -16,22 +25,39 @@ vi.mock('../../src/abi/ERC20', async (importOriginal) => {
Contract,
};
});
vi.mock('../../src/model/', async (importOriginal) => {
const actualMods = await importOriginal;

vi.mock('../../src/abi/ERC721', async (importOriginal) => {
const Contract = vi.fn();

Contract.prototype.name = vi.fn();
Contract.prototype.symbol = vi.fn();

return {
Contract,
};
});

vi.mock('../../src/model/', async () => {
const Token = vi.fn();
const Erc20Deposit = vi.fn();
const Application = vi.fn();
const Input = vi.fn();
const Erc721Deposit = vi.fn();
const NFT = vi.fn();
return {
...actualMods!,
Application,
Token,
Erc20Deposit,
Erc721Deposit,
Input,
NFT,
};
});

const ApplicationMock = vi.mocked(Application);
const InputMock = vi.mocked(Input);
const NFTStub = vi.mocked(NFT);
const ERC721DepositStub = vi.mocked(Erc721Deposit);

const tokenAddress = dataSlice(input.payload, 1, 21).toLowerCase(); // 20 bytes for address
const from = dataSlice(input.payload, 21, 41).toLowerCase(); // 20 bytes for address
Expand All @@ -40,10 +66,12 @@ const amount = getUint(dataSlice(input.payload, 41, 73)); // 32 bytes for uint25
describe('InputAdded', () => {
let inputAdded: InputAdded;
let erc20;
let erc721: MockedObject<ERC721>;
const mockTokenStorage = new Map();
const mockDepositStorage = new Map();
const mockInputStorage = new Map();
const mockApplicationStorage = new Map();

beforeEach(() => {
inputAdded = new InputAdded(
mockTokenStorage,
Expand All @@ -52,6 +80,7 @@ describe('InputAdded', () => {
mockInputStorage,
);
erc20 = new Contract(ctx, block.header, tokenAddress);
erc721 = vi.mocked(new ERC721(ctx, block.header, tokenAddress));
mockTokenStorage.clear();
mockDepositStorage.clear();
mockApplicationStorage.clear();
Expand Down Expand Up @@ -110,23 +139,27 @@ describe('InputAdded', () => {
expect(handlePayload).toBe(undefined);
});
});

describe('handle', async () => {
test('call with the correct params', async () => {
vi.spyOn(inputAdded, 'handle');
inputAdded.handle(logs[0], block, ctx);
expect(inputAdded.handle).toBeCalledWith(logs[0], block, ctx);
});

test('wrong contract address', async () => {
await inputAdded.handle(logs[1], block, ctx);
expect(mockInputStorage.size).toBe(0);
expect(mockApplicationStorage.size).toBe(0);
expect(mockDepositStorage.size).toBe(0);
});

test('correct contract address', async () => {
await inputAdded.handle(logs[0], block, ctx);
expect(mockApplicationStorage.size).toBe(1);
expect(mockInputStorage.size).toBe(1);
});

test('Erc20Deposit Stored', async () => {
const name = 'SimpleERC20';
const symbol = 'SIM20';
Expand Down Expand Up @@ -174,5 +207,101 @@ describe('InputAdded', () => {
timestamp,
});
});

describe('ERC-721 deposits', () => {
const name = 'BrotherNFT';
const symbol = 'BRUH';

beforeEach(() => {
erc721.name.mockResolvedValue(name);
erc721.symbol.mockResolvedValue(symbol);

// Returning simple object as the Class type for assertion
InputMock.mockImplementationOnce((args) => {
return { ...args } as Input;
});

NFTStub.mockImplementationOnce((args) => {
return { ...args } as NFT;
});

ERC721DepositStub.mockImplementationOnce((args) => {
return { ...args } as Erc721Deposit;
});
});

afterEach(() => {
vi.clearAllMocks();
});

test('should store the token information', async () => {
await inputAdded.handle(logErc721Transfer, block, ctx);

expect(mockTokenStorage.size).toBe(1);
const token = mockTokenStorage.values().next().value;
expect(token.name).toEqual(name);
expect(token.symbol).toEqual(symbol);
});

test('should store the deposit information', async () => {
await inputAdded.handle(logErc721Transfer, block, ctx);

expect(mockDepositStorage.size).toBe(1);
const deposit = mockDepositStorage.values().next().value;
expect(deposit.id).toEqual(
'0x0be010fa7e70d74fa8b6729fe1ae268787298f54-1',
);
expect(deposit.from).toEqual(
logErc721Transfer.transaction.from,
);
expect(deposit.tokenIdx).toEqual(1n);
expect(deposit.token).toEqual({
id: '0x7a3cc9c0408887a030a0354330c36a9cd681aa7e',
name,
symbol,
});
});

test('should assign the erc721 deposit information correctly into the input', async () => {
await inputAdded.handle(logErc721Transfer, block, ctx);

expect(mockInputStorage.size).toBe(1);
const input = mockInputStorage.values().next().value;
expect(input.erc721Deposit).toEqual({
from: '0xa074683b5be015f053b5dceb064c41fc9d11b6e5',
id: '0x0be010fa7e70d74fa8b6729fe1ae268787298f54-1',
token: {
id: '0x7a3cc9c0408887a030a0354330c36a9cd681aa7e',
name,
symbol,
},
tokenIdx: 1n,
});
});

test('should handle the absence of name and symbol methods in the ERC-721 contract', async () => {
erc721.name.mockRejectedValue(
new Error('No name method implemented on contract'),
);
erc721.symbol.mockRejectedValue(
new Error('No symbol method implemented on contract'),
);

await inputAdded.handle(logErc721Transfer, block, ctx);

expect(mockInputStorage.size).toBe(1);
const input = mockInputStorage.values().next().value;
expect(input.erc721Deposit).toEqual({
from: '0xa074683b5be015f053b5dceb064c41fc9d11b6e5',
id: '0x0be010fa7e70d74fa8b6729fe1ae268787298f54-1',
token: {
id: '0x7a3cc9c0408887a030a0354330c36a9cd681aa7e',
name: null,
symbol: null,
},
tokenIdx: 1n,
});
});
});
});
});
49 changes: 48 additions & 1 deletion tests/stubs/params.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,22 @@ import { vi } from 'vitest';
import {
CartesiDAppFactoryAddress,
ERC20PortalAddress,
InputBoxAddress,
} from '../../src/config';
import { Input } from '../../src/model';

vi.mock('@subsquid/logger', async (importOriginal) => {
const actualMods = await importOriginal;
const Logger = vi.fn();
Logger.prototype.warn = vi.fn();
Logger.prototype.info = vi.fn();
Logger.prototype.error = vi.fn();
return {
...actualMods!,
Logger,
};
});

vi.mock('@subsquid/typeorm-store', async (importOriginal) => {
const actualMods = await importOriginal;
const Store = vi.fn();
Expand All @@ -28,6 +32,7 @@ vi.mock('@subsquid/typeorm-store', async (importOriginal) => {
});
const payload =
'0x494e5345525420494e544f20636572746966696572202056414c554553202827307866434432423566316346353562353643306632323464614439394331346234454530393237346433272c3130202c273078664344324235663163463535623536433066323234646144393943313462344545303932373464332729';

export const input = {
id: '0x60a7048c3136293071605a4eaffef49923e981cc-0',
application: {
Expand All @@ -44,17 +49,55 @@ export const input = {
blockNumber: 4040941n,
blockHash:
'0xce6a0d404b4201b3bd4fb8309df0b6a64f6a5d7b71fa89bf2737d4574c58b32f',
erc721Deposit: null,
erc20Deposit: null,
transactionHash:
'0x6a3d76983453c0f74188bd89e01576c35f9d9b02daecdd49f7171aeb2bd3dc78',
} satisfies Input;

export const logErc721Transfer = {
id: '0004867730-000035-2c78f',
address: InputBoxAddress,
logIndex: 35,
transactionIndex: 24,
topics: [
'0x6aaa400068bf4ca337265e2a1e1e841f66b8597fd5b452fdc52a44bed28a0784',
'0x0000000000000000000000000be010fa7e70d74fa8b6729fe1ae268787298f54',
'0x0000000000000000000000000000000000000000000000000000000000000001',
],
data: '0x000000000000000000000000237f8dd094c0e47f4236f12b4fa01d6dae89fb87000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000c87a3cc9c0408887a030a0354330c36a9cd681aa7ea074683b5be015f053b5dceb064c41fc9d11b6e500000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
block: {
id: '0004867730-2c78f',
height: 4867730,
hash: '0x2c78fb73f84f2755f65533652983578bcf89a68ad173e756bc631b4d0d242b53',
parentHash:
'0x1bb7d54bde1c3dda41c6cc5ab40ad04b855d1ce5dec4175571dd158d3134ec3e',
timestamp: 1702321200000,
},
transaction: {
id: '0004867730-000024-2c78f',
transactionIndex: 24,
from: '0xa074683b5be015f053b5dceb064c41fc9d11b6e5',
to: '0x237f8dd094c0e47f4236f12b4fa01d6dae89fb87',
hash: '0x47c53eeddc2f927ef2a7a3dd9a95bfd70ecfda2c4efdf10a16c48ca98c86b881',
value: 0,
block: {
id: '0004867730-2c78f',
height: 4867730,
hash: '0x2c78fb73f84f2755f65533652983578bcf89a68ad173e756bc631b4d0d242b53',
parentHash:
'0x1bb7d54bde1c3dda41c6cc5ab40ad04b855d1ce5dec4175571dd158d3134ec3e',
timestamp: 1702321200000,
},
},
};

export const logs = [
{
id: '0004411683-000001-cae3a',
logIndex: 1,
transactionIndex: 1,
address: '0x59b22d57d4f067708ab0c00552767405926dc768',
address: InputBoxAddress,
topics: [
'0x6aaa400068bf4ca337265e2a1e1e841f66b8597fd5b452fdc52a44bed28a0784',
'0x0000000000000000000000000be010fa7e70d74fa8b6729fe1ae268787298f54',
Expand Down Expand Up @@ -161,6 +204,7 @@ export const logs = [
},
},
];

export const block = {
header: {
id: '1234567890',
Expand All @@ -174,15 +218,18 @@ export const block = {
traces: [],
stateDiffs: [],
};

export const token = {
decimals: 18,
id: '0x059c7507b973d1512768c06f32a813bc93d83eb2',
name: 'SimpleERC20',
symbol: 'SIM20',
};

const consoleSink = vi.fn();
const em = vi.fn();
const logger = new Logger(consoleSink, 'app');

const store = new Store(em);
export const ctx = {
_chain: {} as unknown as Chain,
Expand Down

0 comments on commit 94d6846

Please sign in to comment.