diff --git a/packages/eth-rpc-adapter/src/__tests__/endpoint-tests/endpoint.ts b/packages/eth-rpc-adapter/src/__tests__/endpoint-tests/endpoint.ts index 738a6c356..167a7e0e4 100644 --- a/packages/eth-rpc-adapter/src/__tests__/endpoint-tests/endpoint.ts +++ b/packages/eth-rpc-adapter/src/__tests__/endpoint-tests/endpoint.ts @@ -610,51 +610,6 @@ describe('endpoint', () => { }); - describe('eth_getCode', () => { - const preCompileAddresses = [ - '0x0000000000000000000100000000000000000001', // AUSD - '0x0000000000000000000200000000000000000001', // LP_ACA_AUSD - '0x0000000000000000000000000000000000000803', // DEX - ]; - - const tags = ['latest', 'earliest', 'finalized', 'safe']; - - it('get correct precompile token code', async () => { - for (const addr of preCompileAddresses) { - for (const t of tags) { - const res = (await eth_getCode([addr, t])).data.result; - expect(res.length).to.greaterThan(2); - } - } - }); - - it.skip('get correct user deployed contract code', async () => {}); - - it('returns empty for pending tag or non-exist contract address', async () => { - const randAddr = '0x1ebEc3D7fd088d9eE4B6d8272788f028e5122218'; - for (const t of [...tags, 'pending']) { - const res = (await eth_getCode([randAddr, t])).data.result; - expect(res).to.equal('0x'); - } - }); - - it('supports calling historical blocks', async () => { - const dexAddr = '0x0230135fded668a3f7894966b14f42e65da322e4'; // created at block 5 - expect((await eth_getCode([dexAddr, { blockNumber: 1 }])).data.result).to.equal('0x'); - expect((await eth_getCode([dexAddr, { blockNumber: 5 }])).data.result.length).to.greaterThan(2); - expect((await eth_getCode([dexAddr, { blockNumber: 8 }])).data.result.length).to.greaterThan(2); - expect((await eth_getCode([dexAddr, 7])).data.result.length).to.greaterThan(2); - }); - }); - - describe('net_runtimeVersion', () => { - it('get correct runtime version', async () => { - const version = (await net_runtimeVersion([])).data.result; - - expect(version).to.be.gt(2000); - }); - }); - describe('eth_getBlockByNumber', () => { if (process.env.SKIP_PUBLIC) { console.log('public karura tests are skipped ❗'); @@ -749,219 +704,6 @@ describe('endpoint', () => { }); }); - describe('eth_subscribe', () => { - const provider = new EvmRpcProvider(NODE_RPC_URL); - const aca = new Contract(ADDRESS.ACA, TokenABI.abi, wallet1.connect(provider)); - - const notifications: any[] = []; - let subId0; - let subId1; - let subId2; - let subId3; - let ws: WebSocket; - - beforeAll(() => { - // these has to be in , since everything outside of will be globally executed before any - // also, instantiating ws (next line) has to be inside , otherwise there will be mysterious failure... - ws = new WebSocket(WS_URL); - ws.on('open', () => { - ws.on('message', data => { - const parsedData = JSON.parse(data.toString()); - notifications.push(parsedData); - }); - - ws.send( - JSON.stringify({ - jsonrpc: '2.0', - id: 0, - method: 'eth_subscribe', - params: ['newHeads'], - }) - ); - - ws.send( - JSON.stringify({ - jsonrpc: '2.0', - id: 1, - method: 'eth_subscribe', - params: ['logs', {}], - }) - ); - - ws.send( - JSON.stringify({ - jsonrpc: '2.0', - id: 2, - method: 'eth_subscribe', - params: [ - 'logs', - { - topics: [ - '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', // transfer - null, - ['0x000000000000000000000000b00cb924ae22b2bbb15e10c17258d6a2af980421'], - ], - }, - ], - }) - ); - - ws.send( - JSON.stringify({ - jsonrpc: '2.0', - id: 3, - method: 'eth_subscribe', - params: [ - 'logs', - { - topics: [ - '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55aaaaaaaaaaa', // shouldn't match - ], - }, - ], - }) - ); - }); - }); - - afterAll(async () => { - await provider.disconnect(); - ws.close(); - }); - - it('get correct subscrption notification', async () => { - await provider.isReady(); - await aca.transfer(evmAccounts[1].evmAddress, 111222333444555); - - await sleep(3000); // give ws some time to notify - - subId0 = notifications.find(n => n.id === 0).result; - subId1 = notifications.find(n => n.id === 1).result; - subId2 = notifications.find(n => n.id === 2).result; - subId3 = notifications.find(n => n.id === 3).result; - - const notification0 = notifications.find(n => n.params?.subscription === subId0); // new block - const notification1 = notifications.find(n => n.params?.subscription === subId1); // ACA transfer - const notification2 = notifications.find(n => n.params?.subscription === subId2); // ACA transfer - const notification3 = notifications.find(n => n.params?.subscription === subId3); // no match - - const curBlock = (await eth_blockNumber()).data.result; - const curBlockInfo = (await eth_getBlockByNumber([curBlock, false])).data.result; - - expect(notification0).to.deep.contains({ - jsonrpc: '2.0', - method: 'eth_subscription', - params: { - subscription: subId0, - result: curBlockInfo, - }, - }); - - await sleep(10000); // give subql some time to index - const expectedLog = ( - await eth_getLogs([ - { - blockHash: curBlockInfo.hash, - }, - ]) - ).data.result; - - expect(expectedLog.length).to.equal(1); - delete (expectedLog[0] as any).removed; - - expect(notification1).to.deep.contains({ - jsonrpc: '2.0', - method: 'eth_subscription', - params: { - subscription: subId1, - result: expectedLog[0], - }, - }); - - expect(notification2).to.deep.contains({ - jsonrpc: '2.0', - method: 'eth_subscription', - params: { - subscription: subId2, - result: expectedLog[0], - }, - }); - - expect(notification3).to.equal(undefined); - }); - - it('unsubscribe works', async () => { - notifications.length = 0; - - let reqId = 10; - const unsubscribe = async (id: string) => { - ws.send( - JSON.stringify({ - jsonrpc: '2.0', - id: reqId++, - method: 'eth_unsubscribe', - params: [id], - }) - ); - - await sleep(300); // delay each msg to make sure result order is correct - }; - - await unsubscribe(subId0); - await unsubscribe(subId1); - await unsubscribe(subId3); - await unsubscribe(Wallet.createRandom().address); - - await sleep(3000); // give ws some time to notify - - expect(notifications).to.deep.equal([ - { id: 10, jsonrpc: '2.0', result: true }, - { id: 11, jsonrpc: '2.0', result: true }, - { id: 12, jsonrpc: '2.0', result: true }, - { id: 13, jsonrpc: '2.0', result: false }, - ]); - - // only sub2 is left - notifications.length = 0; - await aca.transfer(evmAccounts[1].evmAddress, 1234567654321); - - await sleep(10000); // give ws some time to notify - - const notification0 = notifications.find(n => n.params?.subscription === subId0); // no match - const notification1 = notifications.find(n => n.params?.subscription === subId1); // no match - const notification2 = notifications.find(n => n.params?.subscription === subId2); // ACA transfer - const notification3 = notifications.find(n => n.params?.subscription === subId3); // no match - - // after unsubscribe they should not be notified anymore - expect(notification0).to.equal(undefined); - expect(notification1).to.equal(undefined); - expect(notification3).to.equal(undefined); - - await sleep(10000); // give subql some time to index - const curBlock = (await eth_blockNumber()).data.result; - const curBlockInfo = (await eth_getBlockByNumber([curBlock, false])).data.result; - const expectedLog = ( - await eth_getLogs([ - { - blockHash: curBlockInfo.hash, - }, - ]) - ).data.result; - - expect(expectedLog.length).to.equal(1); - delete (expectedLog[0] as any).removed; - - expect(notification2).to.deep.contains({ - jsonrpc: '2.0', - method: 'eth_subscription', - params: { - subscription: subId2, - result: expectedLog[0], - }, - }); - }); - }); - describe('eth_newBlockFilter', () => { const provider = new EvmRpcProvider(NODE_RPC_URL); const aca = new Contract(ADDRESS.ACA, TokenABI.abi, wallet1.connect(provider)); diff --git a/packages/eth-rpc-adapter/src/__tests__/endpoint-tests/eth_getCode.test.ts b/packages/eth-rpc-adapter/src/__tests__/endpoint-tests/eth_getCode.test.ts new file mode 100644 index 000000000..a722218c7 --- /dev/null +++ b/packages/eth-rpc-adapter/src/__tests__/endpoint-tests/eth_getCode.test.ts @@ -0,0 +1,68 @@ +import { + ACA as ACA_ADDR, + LP_LCDOT_DOT, +} from '@acala-network/contracts/utils/AcalaAddress'; +import { BlockTagish, Eip1898BlockTag } from '@acala-network/eth-providers'; +import { Contract, Wallet } from 'ethers'; +import { beforeAll, describe, expect, it } from 'vitest'; + +import { + deployErc20, + eth_blockNumber, + eth_getCode, + testSetup, +} from '../utils'; + +const { wallet } = testSetup; + +const PRE_DEPLOYED_ADDRS = [ + ACA_ADDR, + LP_LCDOT_DOT, +]; + +const tags = ['latest', 'earliest', 'finalized', 'safe']; + +describe('eth_getCode', () => { + let token: Contract; + let tokenDeployedBlock: number; + + beforeAll(async () => { + token = await deployErc20(wallet); + tokenDeployedBlock = Number((await eth_blockNumber()).data.result); + }); + + it('can get contract code', async () => { + const allAddrs = PRE_DEPLOYED_ADDRS.concat(token.address as any); + + for (const addr of allAddrs) { + for (const t of tags) { + const res = (await eth_getCode([addr, t])).data.result; + + if (t === 'earliest') { + expect(res).to.equal('0x'); + } else { + expect(res.length).to.greaterThan(2); + } + } + } + }); + + it('returns empty for pending tag or non-exist contract address', async () => { + const randAddr = Wallet.createRandom().address; + for (const t of [...tags, 'pending']) { + const res = (await eth_getCode([randAddr, t])).data.result; + expect(res).to.equal('0x'); + } + }); + + it('supports calling historical blocks', async () => { + const _getTokenCode = async (blockTag: BlockTagish | Eip1898BlockTag) => + (await eth_getCode([token.address, blockTag])).data.result; + + expect((await _getTokenCode('earliest'))).to.equal('0x'); + expect((await _getTokenCode({ blockNumber: tokenDeployedBlock - 1 }))).to.equal('0x'); + + expect((await _getTokenCode('latest')).length).to.greaterThan(2); + expect((await _getTokenCode({ blockNumber: tokenDeployedBlock })).length).to.greaterThan(2); + }); +}); diff --git a/packages/eth-rpc-adapter/src/__tests__/endpoint-tests/misc.test.ts b/packages/eth-rpc-adapter/src/__tests__/endpoint-tests/misc.test.ts index acdcd9070..1cef619b6 100644 --- a/packages/eth-rpc-adapter/src/__tests__/endpoint-tests/misc.test.ts +++ b/packages/eth-rpc-adapter/src/__tests__/endpoint-tests/misc.test.ts @@ -5,6 +5,7 @@ import { eth_blockNumber, eth_getEthGas, net_listening, + net_runtimeVersion, } from '../utils'; describe('eth_accounts', () => { @@ -21,6 +22,14 @@ describe('net_listening', () => { }); }); +describe('net_runtimeVersion', () => { + it('get correct runtime version', async () => { + const version = (await net_runtimeVersion([])).data.result; + + expect(version).to.be.gte(2250); + }); +}); + describe('eth_getEthGas', () => { it('get correct default contract deployment eth gas params', async () => { const gasLimit = 21000000;