From e653ad5ec0348d93f71922d16c6371de01b9906a Mon Sep 17 00:00:00 2001 From: Michael Wang <44713145+mzywang@users.noreply.github.com> Date: Mon, 20 May 2024 13:08:47 -0400 Subject: [PATCH] add subgraph unit tests --- Dockerfile | 22 +++ package.json | 3 + src/utils/index.ts | 4 +- src/utils/staticTokenDefinition.ts | 73 +++++++- src/utils/token.ts | 24 ++- tests/.bin/handlemint.wasm | Bin 0 -> 57444 bytes tests/.bin/handlenewpool.wasm | Bin 0 -> 24002 bytes tests/.bin/handlepoolcreated.wasm | Bin 0 -> 21694 bytes tests/.docker/Dockerfile | 22 +++ tests/.latest.json | 4 + tests/handleMint.test.ts | 70 ++++++++ tests/handlePoolCreated.test.ts | 280 +++++++++++++++++++++++++++++ yarn.lock | 12 ++ 13 files changed, 498 insertions(+), 16 deletions(-) create mode 100644 Dockerfile create mode 100644 tests/.bin/handlemint.wasm create mode 100644 tests/.bin/handlenewpool.wasm create mode 100644 tests/.bin/handlepoolcreated.wasm create mode 100644 tests/.docker/Dockerfile create mode 100644 tests/.latest.json create mode 100644 tests/handleMint.test.ts create mode 100644 tests/handlePoolCreated.test.ts diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..281833a6 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,22 @@ +FROM --platform=linux/x86_64 ubuntu:22.04 + +ARG DEBIAN_FRONTEND=noninteractive + +ENV ARGS="" + +RUN apt update \ + && apt install -y sudo curl postgresql postgresql-contrib + +RUN curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash - \ + && sudo apt-get install -y nodejs + +RUN curl -OL https://github.com/LimeChain/matchstick/releases/download/0.6.0/binary-linux-22 \ + && chmod a+x binary-linux-22 + +RUN mkdir matchstick +WORKDIR /matchstick + +# Commenting out for now as it seems there's no need to copy when using bind mount +# COPY ./ . + +CMD ../binary-linux-22 ${ARGS} \ No newline at end of file diff --git a/package.json b/package.json index 14867ded..17e6b4d8 100644 --- a/package.json +++ b/package.json @@ -6,9 +6,11 @@ "scripts": { "lint": "eslint . --ext .ts --fix", "build": "run-s codegen && graph build", + "build:docker": "docker build -t matchstick .", "buildonly": "graph build", "deploy:alchemy": "graph deploy --node https://subgraphs.alchemy.com/api/subgraphs/deploy --ipfs https://ipfs.satsuma.xyz", "codegen": "graph codegen --output-dir src/types/", + "test": "graph test -d", "create-local": "graph create ianlapham/uniswap-v3 --node http://127.0.0.1:8020", "deploy-local": "graph deploy ianlapham/uniswap-v3 --debug --ipfs http://localhost:5001 --node http://127.0.0.1:8020", "deploy": "graph deploy ianlapham/uniswap-v3-subgraph --ipfs https://api.thegraph.com/ipfs/ --node https://api.thegraph.com/deploy/ --debug", @@ -24,6 +26,7 @@ "@uniswap/eslint-config": "^1.2.0", "eslint": "^8.57.0", "eslint-config-prettier": "^6.1.0", + "matchstick-as": "^0.6.0", "npm-run-all": "^4.1.5", "prettier": "^1.18.2", "typescript": "^3.5.2" diff --git a/src/utils/index.ts b/src/utils/index.ts index 69017d27..c9ba3372 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -77,8 +77,10 @@ export function equalToZero(value: BigDecimal): boolean { return false } +export const NULL_ETH_HEX_STRING = '0x0000000000000000000000000000000000000000000000000000000000000001' + export function isNullEthValue(value: string): boolean { - return value == '0x0000000000000000000000000000000000000000000000000000000000000001' + return value == NULL_ETH_HEX_STRING } export function bigDecimalExp18(): BigDecimal { diff --git a/src/utils/staticTokenDefinition.ts b/src/utils/staticTokenDefinition.ts index e2662764..f7be3000 100644 --- a/src/utils/staticTokenDefinition.ts +++ b/src/utils/staticTokenDefinition.ts @@ -1,4 +1,4 @@ -import { Address, BigInt } from '@graphprotocol/graph-ts' +import { Address, BigInt, log } from '@graphprotocol/graph-ts' // Initialize a Token Definition with the attributes export class StaticTokenDefinition { @@ -14,38 +14,38 @@ export class StaticTokenDefinition { address: Address.fromString('0xe0b7927c4af23765cb51314a0e0521a9645f0e2a'), symbol: 'DGD', name: 'DGD', - decimals: BigInt.fromI32(9), + decimals: BigInt.fromI32(9) }, { address: Address.fromString('0x7fc66500c84a76ad7e9c93437bfc5ac33e2ddae9'), symbol: 'AAVE', name: 'Aave Token', - decimals: BigInt.fromI32(18), + decimals: BigInt.fromI32(18) }, { address: Address.fromString('0xeb9951021698b42e4399f9cbb6267aa35f82d59d'), symbol: 'LIF', name: 'Lif', - decimals: BigInt.fromI32(18), + decimals: BigInt.fromI32(18) }, { address: Address.fromString('0xbdeb4b83251fb146687fa19d1c660f99411eefe3'), symbol: 'SVD', name: 'savedroid', - decimals: BigInt.fromI32(18), + decimals: BigInt.fromI32(18) }, { address: Address.fromString('0xbb9bc244d798123fde783fcc1c72d3bb8c189413'), symbol: 'TheDAO', name: 'TheDAO', - decimals: BigInt.fromI32(16), + decimals: BigInt.fromI32(16) }, { address: Address.fromString('0x38c6a68304cdefb9bec48bbfaaba5c5b47818bb2'), symbol: 'HPB', name: 'HPBCoin', - decimals: BigInt.fromI32(18), - }, + decimals: BigInt.fromI32(18) + } ] return staticDefinitions } @@ -67,3 +67,60 @@ export class StaticTokenDefinition { return null } } + +export const getStaticDefinition = ( + tokenAddress: Address, + staticDefinitions: Array +): StaticTokenDefinition | null => { + const tokenAddressHex = tokenAddress.toHexString() + + // Search the definition using the address + for (let i = 0; i < staticDefinitions.length; i++) { + const staticDefinition = staticDefinitions[i] + if (staticDefinition.address.toHexString() == tokenAddressHex) { + return staticDefinition + } + } + + // If not found, return null + return null +} + +export const STATIC_TOKEN_DEFINITIONS: Array = [ + { + address: Address.fromString('0xe0b7927c4af23765cb51314a0e0521a9645f0e2a'), + symbol: 'DGD', + name: 'DGD', + decimals: BigInt.fromI32(9) + }, + { + address: Address.fromString('0x7fc66500c84a76ad7e9c93437bfc5ac33e2ddae9'), + symbol: 'AAVE', + name: 'Aave Token', + decimals: BigInt.fromI32(18) + }, + { + address: Address.fromString('0xeb9951021698b42e4399f9cbb6267aa35f82d59d'), + symbol: 'LIF', + name: 'Lif', + decimals: BigInt.fromI32(18) + }, + { + address: Address.fromString('0xbdeb4b83251fb146687fa19d1c660f99411eefe3'), + symbol: 'SVD', + name: 'savedroid', + decimals: BigInt.fromI32(18) + }, + { + address: Address.fromString('0xbb9bc244d798123fde783fcc1c72d3bb8c189413'), + symbol: 'TheDAO', + name: 'TheDAO', + decimals: BigInt.fromI32(16) + }, + { + address: Address.fromString('0x38c6a68304cdefb9bec48bbfaaba5c5b47818bb2'), + symbol: 'HPB', + name: 'HPBCoin', + decimals: BigInt.fromI32(18) + } +] diff --git a/src/utils/token.ts b/src/utils/token.ts index bacfdac8..9bb131e1 100644 --- a/src/utils/token.ts +++ b/src/utils/token.ts @@ -4,9 +4,13 @@ import { ERC20 } from '../types/Factory/ERC20' import { ERC20NameBytes } from '../types/Factory/ERC20NameBytes' import { ERC20SymbolBytes } from '../types/Factory/ERC20SymbolBytes' import { isNullEthValue } from '.' -import { StaticTokenDefinition } from './staticTokenDefinition' +import { StaticTokenDefinition, getStaticDefinition, STATIC_TOKEN_DEFINITIONS } from './staticTokenDefinition' +import { log } from 'matchstick-as' -export function fetchTokenSymbol(tokenAddress: Address): string { +export function fetchTokenSymbol( + tokenAddress: Address, + staticTokenDefinitions: StaticTokenDefinition[] = STATIC_TOKEN_DEFINITIONS +): string { const contract = ERC20.bind(tokenAddress) const contractSymbolBytes = ERC20SymbolBytes.bind(tokenAddress) @@ -21,7 +25,7 @@ export function fetchTokenSymbol(tokenAddress: Address): string { symbolValue = symbolResultBytes.value.toString() } else { // try with the static definition - const staticTokenDefinition = StaticTokenDefinition.fromAddress(tokenAddress) + const staticTokenDefinition = getStaticDefinition(tokenAddress, staticTokenDefinitions) if (staticTokenDefinition != null) { symbolValue = staticTokenDefinition.symbol } @@ -34,7 +38,10 @@ export function fetchTokenSymbol(tokenAddress: Address): string { return symbolValue } -export function fetchTokenName(tokenAddress: Address): string { +export function fetchTokenName( + tokenAddress: Address, + staticTokenDefinitions: StaticTokenDefinition[] = STATIC_TOKEN_DEFINITIONS +): string { const contract = ERC20.bind(tokenAddress) const contractNameBytes = ERC20NameBytes.bind(tokenAddress) @@ -49,7 +56,7 @@ export function fetchTokenName(tokenAddress: Address): string { nameValue = nameResultBytes.value.toString() } else { // try with the static definition - const staticTokenDefinition = StaticTokenDefinition.fromAddress(tokenAddress) + const staticTokenDefinition = getStaticDefinition(tokenAddress, staticTokenDefinitions) if (staticTokenDefinition != null) { nameValue = staticTokenDefinition.name } @@ -72,7 +79,10 @@ export function fetchTokenTotalSupply(tokenAddress: Address): BigInt { return totalSupplyValue } -export function fetchTokenDecimals(tokenAddress: Address): BigInt | null { +export function fetchTokenDecimals( + tokenAddress: Address, + staticTokenDefinitions: StaticTokenDefinition[] = STATIC_TOKEN_DEFINITIONS +): BigInt | null { const contract = ERC20.bind(tokenAddress) // try types uint8 for decimals const decimalResult = contract.try_decimals() @@ -83,7 +93,7 @@ export function fetchTokenDecimals(tokenAddress: Address): BigInt | null { } } else { // try with the static definition - const staticTokenDefinition = StaticTokenDefinition.fromAddress(tokenAddress) + const staticTokenDefinition = getStaticDefinition(tokenAddress, staticTokenDefinitions) if (staticTokenDefinition) { return staticTokenDefinition.decimals } diff --git a/tests/.bin/handlemint.wasm b/tests/.bin/handlemint.wasm new file mode 100644 index 0000000000000000000000000000000000000000..c3860fd0a88b00a14c16685743fbf906175a0e99 GIT binary patch literal 57444 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 Tvdl-#3jG@$r?WzSrSty)aKmtM literal 0 HcmV?d00001 diff --git a/tests/.bin/handlenewpool.wasm b/tests/.bin/handlenewpool.wasm new file mode 100644 index 0000000000000000000000000000000000000000..3b5b75b2e07ab027fb7c9a76e14f77ed701a4079 GIT binary patch literal 24002 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 SA?slFcKLoahaW33gZ~3yujQlw literal 0 HcmV?d00001 diff --git a/tests/.docker/Dockerfile b/tests/.docker/Dockerfile new file mode 100644 index 00000000..e13a03c3 --- /dev/null +++ b/tests/.docker/Dockerfile @@ -0,0 +1,22 @@ +FROM --platform=linux/x86_64 ubuntu:22.04 + +ARG DEBIAN_FRONTEND=noninteractive + +ENV ARGS="" + +RUN apt update \ + && apt install -y sudo curl postgresql postgresql-contrib + +RUN curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash - \ + && sudo apt-get install -y nodejs + +RUN curl -OL https://github.com/LimeChain/matchstick/releases/download/0.6.0/binary-linux-22 \ + && chmod a+x binary-linux-22 + +RUN mkdir matchstick +WORKDIR /matchstick + +# Commenting out for now as it seems there's no need to copy when using bind mount +# COPY ./ . + +CMD ../binary-linux-22 ${ARGS} diff --git a/tests/.latest.json b/tests/.latest.json new file mode 100644 index 00000000..3aa15d03 --- /dev/null +++ b/tests/.latest.json @@ -0,0 +1,4 @@ +{ + "version": "0.6.0", + "timestamp": 1716213533842 +} \ No newline at end of file diff --git a/tests/handleMint.test.ts b/tests/handleMint.test.ts new file mode 100644 index 00000000..e85b34cd --- /dev/null +++ b/tests/handleMint.test.ts @@ -0,0 +1,70 @@ +import { Address, BigInt, ethereum } from '@graphprotocol/graph-ts' +import { assert, beforeAll, createMockedFunction, describe, log, newMockEvent, test } from 'matchstick-as' +import { PoolCreated } from '../src/types/Factory/Factory' +import { handlePoolCreated } from '../src/mappings/factory' +import { FACTORY_ADDRESS } from '../src/utils/constants' + +const USDC_MAINNET_ADDRESS = '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' +const WETH_MAINNET_ADDRESS = '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2' +const USDC_WETH_03_MAINNET_POOL = '0x8ad599c3a0ff1de082011efddc58f1908eb6e6d8' +const POOL_FEE_TIER_03 = 3000 +const POOL_TICK_SPACING_03 = 60 + +describe('handleMint', () => { + beforeAll(() => { + // todo: dedupe this with handlePoolCreated + const mockEvent = newMockEvent() + const token0Address = Address.fromString(USDC_MAINNET_ADDRESS) + const token1Address = Address.fromString(WETH_MAINNET_ADDRESS) + const poolAddress = Address.fromString(USDC_WETH_03_MAINNET_POOL) + const parameters = [ + new ethereum.EventParam('token0', ethereum.Value.fromAddress(token0Address)), + new ethereum.EventParam('token1', ethereum.Value.fromAddress(token1Address)), + new ethereum.EventParam('fee', ethereum.Value.fromI32(POOL_FEE_TIER_03)), + new ethereum.EventParam('tickSpacing', ethereum.Value.fromI32(POOL_TICK_SPACING_03)), + new ethereum.EventParam('pool', ethereum.Value.fromAddress(poolAddress)) + ] + + const poolCreatedEvent = new PoolCreated( + mockEvent.address, + mockEvent.logIndex, + mockEvent.transactionLogIndex, + mockEvent.logType, + mockEvent.block, + mockEvent.transaction, + parameters, + mockEvent.receipt + ) + + // create mock contract calls for token0 + createMockedFunction(token0Address, 'symbol', 'symbol():(string)').returns([ethereum.Value.fromString('USDC')]) + createMockedFunction(token0Address, 'name', 'name():(string)').returns([ethereum.Value.fromString('USD Coin')]) + createMockedFunction(token0Address, 'totalSupply', 'totalSupply():(uint256)').returns([ + ethereum.Value.fromUnsignedBigInt(BigInt.fromString('300')) + ]) + createMockedFunction(token0Address, 'decimals', 'decimals():(uint32)').returns([ + ethereum.Value.fromUnsignedBigInt(BigInt.fromString('6')) + ]) + + // create mock contract calls for token1 + createMockedFunction(token1Address, 'symbol', 'symbol():(string)').returns([ethereum.Value.fromString('WETH')]) + createMockedFunction(token1Address, 'name', 'name():(string)').returns([ethereum.Value.fromString('Wrapped Ether')]) + createMockedFunction(token1Address, 'totalSupply', 'totalSupply():(uint256)').returns([ + ethereum.Value.fromUnsignedBigInt(BigInt.fromString('100')) + ]) + createMockedFunction(token1Address, 'decimals', 'decimals():(uint32)').returns([ + ethereum.Value.fromUnsignedBigInt(BigInt.fromString('18')) + ]) + + assert.notInStore('Factory', FACTORY_ADDRESS) + assert.notInStore('Pool', USDC_WETH_03_MAINNET_POOL) + assert.notInStore('Token', USDC_MAINNET_ADDRESS) + assert.notInStore('Token', WETH_MAINNET_ADDRESS) + + handlePoolCreated(poolCreatedEvent) + }) + + test('success - mint event', () => { + log.success('mint event success', []) + }) +}) diff --git a/tests/handlePoolCreated.test.ts b/tests/handlePoolCreated.test.ts new file mode 100644 index 00000000..af4054ab --- /dev/null +++ b/tests/handlePoolCreated.test.ts @@ -0,0 +1,280 @@ +import { Address, BigInt, Bytes, ethereum, log } from '@graphprotocol/graph-ts' +import { assert, test, newMockEvent, dataSourceMock, createMockedFunction } from 'matchstick-as/assembly/index' +import { describe, test } from 'matchstick-as/assembly/index' +import { PoolCreated } from '../src/types/Factory/Factory' +import { handlePoolCreated } from '../src/mappings/factory' +import { FACTORY_ADDRESS } from '../src/utils/constants' +import { fetchTokenDecimals, fetchTokenName, fetchTokenSymbol, fetchTokenTotalSupply } from '../src/utils/token' +import { StaticTokenDefinition } from '../src/utils/staticTokenDefinition' +import { NULL_ETH_HEX_STRING } from '../src/utils' + +const USDC_MAINNET_ADDRESS = '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' +const WETH_MAINNET_ADDRESS = '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2' +const USDC_WETH_03_MAINNET_POOL = '0x8ad599c3a0ff1de082011efddc58f1908eb6e6d8' +const POOL_FEE_TIER_03 = 3000 +const POOL_TICK_SPACING_03 = 60 + +describe('handlePoolCreated', () => { + test('success - create a pool', () => { + const mockEvent = newMockEvent() + const token0Address = Address.fromString(USDC_MAINNET_ADDRESS) + const token1Address = Address.fromString(WETH_MAINNET_ADDRESS) + const poolAddress = Address.fromString(USDC_WETH_03_MAINNET_POOL) + const parameters = [ + new ethereum.EventParam('token0', ethereum.Value.fromAddress(token0Address)), + new ethereum.EventParam('token1', ethereum.Value.fromAddress(token1Address)), + new ethereum.EventParam('fee', ethereum.Value.fromI32(POOL_FEE_TIER_03)), + new ethereum.EventParam('tickSpacing', ethereum.Value.fromI32(POOL_TICK_SPACING_03)), + new ethereum.EventParam('pool', ethereum.Value.fromAddress(poolAddress)) + ] + + const poolCreatedEvent = new PoolCreated( + mockEvent.address, + mockEvent.logIndex, + mockEvent.transactionLogIndex, + mockEvent.logType, + mockEvent.block, + mockEvent.transaction, + parameters, + mockEvent.receipt + ) + + // create mock contract calls for token0 + createMockedFunction(token0Address, 'symbol', 'symbol():(string)').returns([ethereum.Value.fromString('USDC')]) + createMockedFunction(token0Address, 'name', 'name():(string)').returns([ethereum.Value.fromString('USD Coin')]) + createMockedFunction(token0Address, 'totalSupply', 'totalSupply():(uint256)').returns([ + ethereum.Value.fromUnsignedBigInt(BigInt.fromString('300')) + ]) + createMockedFunction(token0Address, 'decimals', 'decimals():(uint32)').returns([ + ethereum.Value.fromUnsignedBigInt(BigInt.fromString('6')) + ]) + + // create mock contract calls for token1 + createMockedFunction(token1Address, 'symbol', 'symbol():(string)').returns([ethereum.Value.fromString('WETH')]) + createMockedFunction(token1Address, 'name', 'name():(string)').returns([ethereum.Value.fromString('Wrapped Ether')]) + createMockedFunction(token1Address, 'totalSupply', 'totalSupply():(uint256)').returns([ + ethereum.Value.fromUnsignedBigInt(BigInt.fromString('100')) + ]) + createMockedFunction(token1Address, 'decimals', 'decimals():(uint32)').returns([ + ethereum.Value.fromUnsignedBigInt(BigInt.fromString('18')) + ]) + + assert.notInStore('Factory', FACTORY_ADDRESS) + assert.notInStore('Pool', USDC_WETH_03_MAINNET_POOL) + assert.notInStore('Token', USDC_MAINNET_ADDRESS) + assert.notInStore('Token', WETH_MAINNET_ADDRESS) + + handlePoolCreated(poolCreatedEvent) + + assert.fieldEquals('Factory', FACTORY_ADDRESS, 'poolCount', '1') + assert.fieldEquals('Factory', FACTORY_ADDRESS, 'totalVolumeETH', '0') + assert.fieldEquals('Factory', FACTORY_ADDRESS, 'totalVolumeUSD', '0') + assert.fieldEquals('Factory', FACTORY_ADDRESS, 'untrackedVolumeUSD', '0') + assert.fieldEquals('Factory', FACTORY_ADDRESS, 'totalFeesUSD', '0') + assert.fieldEquals('Factory', FACTORY_ADDRESS, 'totalFeesETH', '0') + assert.fieldEquals('Factory', FACTORY_ADDRESS, 'totalValueLockedETH', '0') + assert.fieldEquals('Factory', FACTORY_ADDRESS, 'totalValueLockedUSD', '0') + assert.fieldEquals('Factory', FACTORY_ADDRESS, 'totalValueLockedETHUntracked', '0') + assert.fieldEquals('Factory', FACTORY_ADDRESS, 'totalValueLockedUSDUntracked', '0') + + assert.fieldEquals('Bundle', '1', 'ethPriceUSD', '0') + + assert.fieldEquals('Token', USDC_MAINNET_ADDRESS, 'symbol', 'USDC') + assert.fieldEquals('Token', USDC_MAINNET_ADDRESS, 'name', 'USD Coin') + assert.fieldEquals('Token', USDC_MAINNET_ADDRESS, 'totalSupply', '300') + assert.fieldEquals('Token', USDC_MAINNET_ADDRESS, 'decimals', '6') + assert.fieldEquals('Token', USDC_MAINNET_ADDRESS, 'derivedETH', '0') + assert.fieldEquals('Token', USDC_MAINNET_ADDRESS, 'volume', '0') + assert.fieldEquals('Token', USDC_MAINNET_ADDRESS, 'volumeUSD', '0') + assert.fieldEquals('Token', USDC_MAINNET_ADDRESS, 'feesUSD', '0') + assert.fieldEquals('Token', USDC_MAINNET_ADDRESS, 'untrackedVolumeUSD', '0') + assert.fieldEquals('Token', USDC_MAINNET_ADDRESS, 'totalValueLocked', '0') + assert.fieldEquals('Token', USDC_MAINNET_ADDRESS, 'totalValueLockedUSD', '0') + assert.fieldEquals('Token', USDC_MAINNET_ADDRESS, 'totalValueLockedUSDUntracked', '0') + assert.fieldEquals('Token', USDC_MAINNET_ADDRESS, 'txCount', '0') + assert.fieldEquals('Token', USDC_MAINNET_ADDRESS, 'poolCount', '0') + assert.fieldEquals('Token', USDC_MAINNET_ADDRESS, 'whitelistPools', `[${USDC_WETH_03_MAINNET_POOL}]`) + + assert.fieldEquals('Token', WETH_MAINNET_ADDRESS, 'symbol', 'WETH') + assert.fieldEquals('Token', WETH_MAINNET_ADDRESS, 'name', 'Wrapped Ether') + assert.fieldEquals('Token', WETH_MAINNET_ADDRESS, 'totalSupply', '100') + assert.fieldEquals('Token', WETH_MAINNET_ADDRESS, 'decimals', '18') + assert.fieldEquals('Token', WETH_MAINNET_ADDRESS, 'derivedETH', '0') + assert.fieldEquals('Token', WETH_MAINNET_ADDRESS, 'volume', '0') + assert.fieldEquals('Token', WETH_MAINNET_ADDRESS, 'volumeUSD', '0') + assert.fieldEquals('Token', WETH_MAINNET_ADDRESS, 'feesUSD', '0') + assert.fieldEquals('Token', WETH_MAINNET_ADDRESS, 'untrackedVolumeUSD', '0') + assert.fieldEquals('Token', WETH_MAINNET_ADDRESS, 'totalValueLocked', '0') + assert.fieldEquals('Token', WETH_MAINNET_ADDRESS, 'totalValueLockedUSD', '0') + assert.fieldEquals('Token', WETH_MAINNET_ADDRESS, 'totalValueLockedUSDUntracked', '0') + assert.fieldEquals('Token', WETH_MAINNET_ADDRESS, 'txCount', '0') + assert.fieldEquals('Token', WETH_MAINNET_ADDRESS, 'poolCount', '0') + assert.fieldEquals('Token', WETH_MAINNET_ADDRESS, 'whitelistPools', `[${USDC_WETH_03_MAINNET_POOL}]`) + + assert.fieldEquals('Pool', USDC_WETH_03_MAINNET_POOL, 'token0', USDC_MAINNET_ADDRESS) + assert.fieldEquals('Pool', USDC_WETH_03_MAINNET_POOL, 'token1', WETH_MAINNET_ADDRESS) + assert.fieldEquals('Pool', USDC_WETH_03_MAINNET_POOL, 'feeTier', POOL_FEE_TIER_03.toString()) + assert.fieldEquals('Pool', USDC_WETH_03_MAINNET_POOL, 'createdAtTimestamp', mockEvent.block.timestamp.toString()) + assert.fieldEquals('Pool', USDC_WETH_03_MAINNET_POOL, 'createdAtBlockNumber', mockEvent.block.number.toString()) + assert.fieldEquals('Pool', USDC_WETH_03_MAINNET_POOL, 'liquidityProviderCount', '0') + assert.fieldEquals('Pool', USDC_WETH_03_MAINNET_POOL, 'txCount', '0') + assert.fieldEquals('Pool', USDC_WETH_03_MAINNET_POOL, 'sqrtPrice', '0') + assert.fieldEquals('Pool', USDC_WETH_03_MAINNET_POOL, 'token0Price', '0') + assert.fieldEquals('Pool', USDC_WETH_03_MAINNET_POOL, 'token1Price', '0') + assert.fieldEquals('Pool', USDC_WETH_03_MAINNET_POOL, 'observationIndex', '0') + assert.fieldEquals('Pool', USDC_WETH_03_MAINNET_POOL, 'totalValueLockedToken0', '0') + assert.fieldEquals('Pool', USDC_WETH_03_MAINNET_POOL, 'totalValueLockedToken1', '0') + assert.fieldEquals('Pool', USDC_WETH_03_MAINNET_POOL, 'totalValueLockedUSD', '0') + assert.fieldEquals('Pool', USDC_WETH_03_MAINNET_POOL, 'totalValueLockedETH', '0') + assert.fieldEquals('Pool', USDC_WETH_03_MAINNET_POOL, 'totalValueLockedUSDUntracked', '0') + assert.fieldEquals('Pool', USDC_WETH_03_MAINNET_POOL, 'volumeToken0', '0') + assert.fieldEquals('Pool', USDC_WETH_03_MAINNET_POOL, 'volumeToken1', '0') + assert.fieldEquals('Pool', USDC_WETH_03_MAINNET_POOL, 'volumeUSD', '0') + assert.fieldEquals('Pool', USDC_WETH_03_MAINNET_POOL, 'feesUSD', '0') + assert.fieldEquals('Pool', USDC_WETH_03_MAINNET_POOL, 'untrackedVolumeUSD', '0') + assert.fieldEquals('Pool', USDC_WETH_03_MAINNET_POOL, 'collectedFeesToken0', '0') + assert.fieldEquals('Pool', USDC_WETH_03_MAINNET_POOL, 'collectedFeesToken1', '0') + assert.fieldEquals('Pool', USDC_WETH_03_MAINNET_POOL, 'collectedFeesUSD', '0') + }) + + describe('fetchTokenSymbol', () => { + test('success - fetch token symbol', () => { + const usdcAddress = Address.fromString(USDC_MAINNET_ADDRESS) + createMockedFunction(usdcAddress, 'symbol', 'symbol():(string)').returns([ethereum.Value.fromString('USDC')]) + const symbol = fetchTokenSymbol(usdcAddress) + assert.stringEquals(symbol, 'USDC') + }) + + test('success - fetch token symbol falls back to bytes call', () => { + const usdcAddress = Address.fromString(USDC_MAINNET_ADDRESS) + createMockedFunction(usdcAddress, 'symbol', 'symbol():(string)').reverts() + createMockedFunction(usdcAddress, 'symbol', 'symbol():(bytes32)').returns([ + ethereum.Value.fromBytes(Bytes.fromUTF8('USDC')) + ]) + const symbol = fetchTokenSymbol(usdcAddress) + assert.stringEquals(symbol, 'USDC') + }) + + test('success - fetch token symbol falls back to static definition', () => { + const usdcAddress = Address.fromString(USDC_MAINNET_ADDRESS) + createMockedFunction(usdcAddress, 'symbol', 'symbol():(string)').reverts() + createMockedFunction(usdcAddress, 'symbol', 'symbol():(bytes32)').returns([ + ethereum.Value.fromBytes(Bytes.fromHexString(NULL_ETH_HEX_STRING)) + ]) + const staticDefinitions: Array = [ + { + address: Address.fromString(USDC_MAINNET_ADDRESS), + symbol: 'USDC', + name: 'USD Coin', + decimals: BigInt.fromI32(6) + } + ] + const symbol = fetchTokenSymbol(usdcAddress, staticDefinitions) + assert.stringEquals(symbol, 'USDC') + }) + + test('failure - fetch token symbol reverts', () => { + const usdcAddress = Address.fromString(USDC_MAINNET_ADDRESS) + createMockedFunction(usdcAddress, 'symbol', 'symbol():(string)').reverts() + createMockedFunction(usdcAddress, 'symbol', 'symbol():(bytes32)').reverts() + const symbol = fetchTokenSymbol(usdcAddress) + assert.stringEquals(symbol, 'unknown') + }) + }) + + describe('fetchTokenName', () => { + test('success - fetch token name', () => { + const usdcAddress = Address.fromString(USDC_MAINNET_ADDRESS) + createMockedFunction(usdcAddress, 'name', 'name():(string)').returns([ethereum.Value.fromString('USD Coin')]) + const name = fetchTokenName(usdcAddress) + assert.stringEquals(name, 'USD Coin') + }) + + test('success - fetch token name falls back to bytes call', () => { + const usdcAddress = Address.fromString(USDC_MAINNET_ADDRESS) + createMockedFunction(usdcAddress, 'name', 'name():(string)').reverts() + createMockedFunction(usdcAddress, 'name', 'name():(bytes32)').returns([ + ethereum.Value.fromBytes(Bytes.fromUTF8('USD Coin')) + ]) + const name = fetchTokenName(usdcAddress) + assert.stringEquals(name, 'USD Coin') + }) + + test('success - fetch token name falls back to static definition', () => { + const usdcAddress = Address.fromString(USDC_MAINNET_ADDRESS) + createMockedFunction(usdcAddress, 'name', 'name():(string)').reverts() + createMockedFunction(usdcAddress, 'name', 'name():(bytes32)').returns([ + ethereum.Value.fromBytes(Bytes.fromHexString(NULL_ETH_HEX_STRING)) + ]) + const staticDefinitions: Array = [ + { + address: Address.fromString(USDC_MAINNET_ADDRESS), + symbol: 'USDC', + name: 'USD Coin', + decimals: BigInt.fromI32(6) + } + ] + const name = fetchTokenName(usdcAddress, staticDefinitions) + assert.stringEquals(name, 'USD Coin') + }) + + test('failure - fetch token name reverts', () => { + const usdcAddress = Address.fromString(USDC_MAINNET_ADDRESS) + createMockedFunction(usdcAddress, 'name', 'name():(string)').reverts() + createMockedFunction(usdcAddress, 'name', 'name():(bytes32)').reverts() + const name = fetchTokenName(usdcAddress) + assert.stringEquals(name, 'unknown') + }) + }) + + describe('fetchTokenTotalSupply', () => { + test('success - fetch token total supply', () => { + const usdcAddress = Address.fromString(USDC_MAINNET_ADDRESS) + createMockedFunction(usdcAddress, 'totalSupply', 'totalSupply():(uint256)').returns([ + ethereum.Value.fromUnsignedBigInt(BigInt.fromString('300')) + ]) + const totalSupply = fetchTokenTotalSupply(usdcAddress) + assert.bigIntEquals(totalSupply, BigInt.fromString('300')) + }) + + test('failure - fetch token total supply reverts', () => { + const usdcAddress = Address.fromString(USDC_MAINNET_ADDRESS) + createMockedFunction(usdcAddress, 'totalSupply', 'totalSupply():(uint256)').reverts() + const totalSupply = fetchTokenTotalSupply(usdcAddress) + assert.bigIntEquals(totalSupply, BigInt.zero()) + }) + }) + + describe('fetchTokenDecimals', () => { + test('success - fetch token decimals', () => { + const usdcAddress = Address.fromString(USDC_MAINNET_ADDRESS) + createMockedFunction(usdcAddress, 'decimals', 'decimals():(uint32)').returns([ + ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(6)) + ]) + const decimals = fetchTokenDecimals(usdcAddress) + assert.assertTrue(decimals == BigInt.fromI32(6)) + }) + + test('success - fetch token decimals falls back to static definition', () => { + const usdcAddress = Address.fromString(USDC_MAINNET_ADDRESS) + createMockedFunction(usdcAddress, 'decimals', 'decimals():(uint32)').reverts() + const staticDefinitions: Array = [ + { + address: Address.fromString(USDC_MAINNET_ADDRESS), + symbol: 'USDC', + name: 'USD Coin', + decimals: BigInt.fromI32(6) + } + ] + const decimals = fetchTokenDecimals(usdcAddress, staticDefinitions) + assert.assertTrue(decimals == BigInt.fromI32(6)) + }) + + test('failure - fetch token decimals reverts', () => { + const usdcAddress = Address.fromString(USDC_MAINNET_ADDRESS) + createMockedFunction(usdcAddress, 'decimals', 'decimals():(uint32)').reverts() + const decimals: BigInt | null = fetchTokenDecimals(usdcAddress) + assert.assertTrue(decimals === null) + }) + }) +}) diff --git a/yarn.lock b/yarn.lock index b4833d2d..2e146812 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3768,6 +3768,13 @@ make-error@^1.1.1: resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== +matchstick-as@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/matchstick-as/-/matchstick-as-0.6.0.tgz#c65296b1f51b1014d605c52067d9b5321ea630e8" + integrity sha512-E36fWsC1AbCkBFt05VsDDRoFvGSdcZg6oZJrtIe/YDBbuFh8SKbR5FcoqDhNWqSN+F7bN/iS2u8Md0SM+4pUpw== + dependencies: + wabt "1.0.24" + md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" @@ -5431,6 +5438,11 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" +wabt@1.0.24: + version "1.0.24" + resolved "https://registry.yarnpkg.com/wabt/-/wabt-1.0.24.tgz#c02e0b5b4503b94feaf4a30a426ef01c1bea7c6c" + integrity sha512-8l7sIOd3i5GWfTWciPL0+ff/FK/deVK2Q6FN+MPz4vfUcD78i2M/49XJTwF6aml91uIiuXJEsLKWMB2cw/mtKg== + wcwidth@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8"