From abace2f3594ded5747f8c313ab56d319e0bb4f0b Mon Sep 17 00:00:00 2001 From: Lyka Labrada Date: Mon, 7 Aug 2023 15:12:04 +0800 Subject: [PATCH 1/5] chore(tests): add tests for evm feature flags --- .../category/evm/evmFeatureFlag.test.ts | 246 ++++++++++++++++++ .../src/containers/DeFiDContainer.ts | 2 +- .../src/containers/NativeChainContainer.ts | 1 - .../src/containers/RegTestContainer/index.ts | 1 - 4 files changed, 247 insertions(+), 3 deletions(-) create mode 100644 packages/jellyfish-api-core/__tests__/category/evm/evmFeatureFlag.test.ts diff --git a/packages/jellyfish-api-core/__tests__/category/evm/evmFeatureFlag.test.ts b/packages/jellyfish-api-core/__tests__/category/evm/evmFeatureFlag.test.ts new file mode 100644 index 000000000..2f8744ea7 --- /dev/null +++ b/packages/jellyfish-api-core/__tests__/category/evm/evmFeatureFlag.test.ts @@ -0,0 +1,246 @@ +import { MasterNodeRegTestContainer } from '@defichain/testcontainers' +import { ContainerAdapterClient } from '../../container_adapter_client' +import { TransferDomainType } from '../../../src/category/account' +import BigNumber from 'bignumber.js' + +describe('EVM feature flags', () => { + let dvmAddr: string, evmAddr: string + const container = new MasterNodeRegTestContainer() + const client = new ContainerAdapterClient(container) + + async function dvmToEvmTransferDomain (): Promise { + const txid = await client.account.transferDomain([ + { + src: { + address: dvmAddr, + amount: '3@DFI', + domain: TransferDomainType.DVM + }, + dst: { + address: evmAddr, + amount: '3@DFI', + domain: TransferDomainType.EVM + } + } + ]) + return txid + } + + async function evmToDvmTransferDomain (): Promise { + const txid = await client.account.transferDomain([ + { + src: { + address: evmAddr, + amount: '2@DFI', + domain: TransferDomainType.EVM + + }, + dst: { + address: dvmAddr, + amount: '2@DFI', + domain: TransferDomainType.DVM + } + } + ]) + return txid + } + + beforeAll(async () => { + await container.start() + await container.waitForWalletCoinbaseMaturity() + + dvmAddr = await container.getNewAddress('dfiAddress', 'legacy') + evmAddr = await container.getNewAddress('eth', 'eth') + + await container.call('utxostoaccount', [{ [dvmAddr]: '100@0' }]) + await container.generate(1) + + await container.call('createtoken', [{ + symbol: 'BTC', + name: 'BTC', + isDAT: true, + mintable: true, + tradeable: true, + collateralAddress: dvmAddr + }]) + await container.generate(1) + }) + + afterAll(async () => { + await container.stop() + }) + + describe('all gov attrs for EVM is set to false', () => { + beforeAll(async () => { + await client.masternode.setGov({ + ATTRIBUTES: { + 'v0/params/feature/evm': 'false', + 'v0/params/feature/transferdomain': 'false', + 'v0/transferdomain/dvm-evm/enabled': 'false', + 'v0/transferdomain/evm-dvm/enabled': 'false' + } + }) + await container.generate(1) + }) + + it('should still successfully get eth address', async () => { + const newEvmAddr = await container.getNewAddress('eth', 'eth') + expect(newEvmAddr).toBeDefined() + }) + + it.only('should still successfully get eth balance', async () => { + const dvmBalances = await client.account.getTokenBalances({}, false) + const [dvmBalance] = dvmBalances[0].split('@') + const evmBalances = await client.account.getTokenBalances({}, false, { includeEth: true }) + const [evmBalance] = evmBalances[0].split('@') + expect(evmBalance).toBeDefined() + expect(new BigNumber(dvmBalance).minus(new BigNumber(evmBalance))) + .toStrictEqual(new BigNumber(0)) + }) + }) + + describe('all gov attrs for EVM is set to true', () => { + beforeAll(async () => { + await client.masternode.setGov({ + ATTRIBUTES: { + 'v0/params/feature/evm': 'true', + 'v0/params/feature/transferdomain': 'true', + 'v0/transferdomain/dvm-evm/enabled': 'true', + 'v0/transferdomain/evm-dvm/enabled': 'true' + } + }) + await container.generate(1) + }) + + it('should successfully transfer domain from DVM to EVM', async () => { + const txid = await dvmToEvmTransferDomain() + await container.generate(1) + expect(typeof txid).toStrictEqual('string') + expect(txid.length).toStrictEqual(64) + }) + + it('should successfully transfer domain from EVM to DVM', async () => { + const txid = await evmToDvmTransferDomain() + expect(typeof txid).toStrictEqual('string') + expect(txid.length).toStrictEqual(64) + }) + }) + + describe('gov attr v0/params/feature/evm is set to false', () => { + beforeAll(async () => { + await client.masternode.setGov({ + ATTRIBUTES: { + 'v0/params/feature/evm': 'false', + 'v0/params/feature/transferdomain': 'true' + } + }) + await container.generate(1) + }) + + it('should fail DVM to EVM transferDomain', async () => { + const promise = dvmToEvmTransferDomain() + await expect(promise).rejects.toThrow('Cannot create tx, EVM is not enabled') + }) + + it('should fail EVM to DVM transferDomain', async () => { + const promise = evmToDvmTransferDomain() + await expect(promise).rejects.toThrow('Cannot create tx, EVM is not enabled') + }) + }) + + describe('gov attr v0/params/feature/transferdomain is set to false', () => { + beforeAll(async () => { + await client.masternode.setGov({ + ATTRIBUTES: { + 'v0/params/feature/evm': 'true', + 'v0/params/feature/transferdomain': 'false' + } + }) + await container.generate(1) + }) + + it('should fail DVM to EVM transferDomain', async () => { + const promise = dvmToEvmTransferDomain() + await expect(promise).rejects.toThrow('Cannot create tx, transfer domain is not enabled') + }) + + it('should fail EVM to DVM transferDomain', async () => { + const promise = evmToDvmTransferDomain() + await expect(promise).rejects.toThrow('Cannot create tx, transfer domain is not enabled') + }) + }) + + describe('gov attr v0/transferdomain/dvm-evm/enabled is set to false', () => { + beforeAll(async () => { + await client.masternode.setGov({ + ATTRIBUTES: { + 'v0/params/feature/evm': 'true', + 'v0/params/feature/transferdomain': 'true', + 'v0/transferdomain/evm-dvm/enabled': 'true', + 'v0/transferdomain/dvm-evm/enabled': 'false' // disabled dvm-evm + } + }) + await container.generate(1) + }) + + it('should not allow DVM to EVM transferDomain', async () => { + const promise = dvmToEvmTransferDomain() + await expect(promise).rejects.toThrow('DVM to EVM is not currently enabled') + }) + + it('should allow EVM to DVM transferDomain', async () => { + const txid = await evmToDvmTransferDomain() + expect(typeof txid).toStrictEqual('string') + expect(txid.length).toStrictEqual(64) + }) + }) + + describe('gov attr v0/transferdomain/evm-dvm/enabled is set to false', () => { + beforeAll(async () => { + await client.masternode.setGov({ + ATTRIBUTES: { + 'v0/params/feature/evm': 'true', + 'v0/params/feature/transferdomain': 'true', + 'v0/transferdomain/dvm-evm/enabled': 'true', + 'v0/transferdomain/evm-dvm/enabled': 'false' // disabled evm-dvm + } + }) + await container.generate(1) + }) + + it('should not allow EVM to DVM transferDomain', async () => { + const promise = evmToDvmTransferDomain() + await expect(promise).rejects.toThrow('EVM to DVM is not currently enabled') + }) + + it('should allow DVM to EVM transferDomain', async () => { + const txid = await dvmToEvmTransferDomain() + expect(typeof txid).toStrictEqual('string') + expect(txid.length).toStrictEqual(64) + }) + }) + + describe('gov attrs v0/transferdomain/dvm-evm/enabled and v0/transferdomain/evm-dvm/enabled are both set to false', () => { + beforeAll(async () => { + await client.masternode.setGov({ + ATTRIBUTES: { + 'v0/params/feature/evm': 'true', + 'v0/params/feature/transferdomain': 'true', + 'v0/transferdomain/dvm-evm/enabled': 'false', // disabled dvm-evm + 'v0/transferdomain/evm-dvm/enabled': 'false' // disabled evm-dvm + } + }) + await container.generate(1) + }) + + it('should not allow EVM to DVM transferDomain', async () => { + const promise = evmToDvmTransferDomain() + await expect(promise).rejects.toThrow('EVM to DVM is not currently enabled') + }) + + it('should not allow DVM to EVM transferDomain', async () => { + const promise = dvmToEvmTransferDomain() + await expect(promise).rejects.toThrow('DVM to EVM is not currently enabled') + }) + }) +}) diff --git a/packages/testcontainers/src/containers/DeFiDContainer.ts b/packages/testcontainers/src/containers/DeFiDContainer.ts index 5ef947693..50c54f29a 100644 --- a/packages/testcontainers/src/containers/DeFiDContainer.ts +++ b/packages/testcontainers/src/containers/DeFiDContainer.ts @@ -36,7 +36,7 @@ export abstract class DeFiDContainer extends DockerContainer { if (process?.env?.DEFICHAIN_DOCKER_IMAGE !== undefined) { return process.env.DEFICHAIN_DOCKER_IMAGE } - return 'defi/defichain:master-91a01aea0' // renovate.json regexManagers + return 'defi/defichain:4.0.0-beta8' // renovate.json regexManagers } public static readonly DefaultStartOptions = { diff --git a/packages/testcontainers/src/containers/NativeChainContainer.ts b/packages/testcontainers/src/containers/NativeChainContainer.ts index 10c6a7ab0..df7f1cf20 100644 --- a/packages/testcontainers/src/containers/NativeChainContainer.ts +++ b/packages/testcontainers/src/containers/NativeChainContainer.ts @@ -119,7 +119,6 @@ export class NativeChainContainer extends GenericContainer { '-grandcentralheight=16', '-grandcentralepilogueheight=17', '-nextnetworkupgradeheight=18', - '-changiintermediateheight=19', '-regtest-skip-loan-collateral-validation', '-regtest-minttoken-simulate-mainnet=0' ], diff --git a/packages/testcontainers/src/containers/RegTestContainer/index.ts b/packages/testcontainers/src/containers/RegTestContainer/index.ts index 11203c079..e667fe6af 100644 --- a/packages/testcontainers/src/containers/RegTestContainer/index.ts +++ b/packages/testcontainers/src/containers/RegTestContainer/index.ts @@ -43,7 +43,6 @@ export class RegTestContainer extends DeFiDContainer { '-grandcentralheight=16', '-grandcentralepilogueheight=17', '-nextnetworkupgradeheight=18', - '-changiintermediateheight=19', '-regtest-skip-loan-collateral-validation', '-regtest-minttoken-simulate-mainnet=0', '-rpc-governance-accept-neutral=1' From 5c36cc48799aad4704e839de605aa2a56a9e8fcc Mon Sep 17 00:00:00 2001 From: Lyka Labrada Date: Mon, 7 Aug 2023 17:28:43 +0800 Subject: [PATCH 2/5] add test case for evmtx creation --- .../category/evm/evmFeatureFlag.test.ts | 46 +++++++++++++++++-- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/packages/jellyfish-api-core/__tests__/category/evm/evmFeatureFlag.test.ts b/packages/jellyfish-api-core/__tests__/category/evm/evmFeatureFlag.test.ts index 2f8744ea7..1e1569f33 100644 --- a/packages/jellyfish-api-core/__tests__/category/evm/evmFeatureFlag.test.ts +++ b/packages/jellyfish-api-core/__tests__/category/evm/evmFeatureFlag.test.ts @@ -4,7 +4,7 @@ import { TransferDomainType } from '../../../src/category/account' import BigNumber from 'bignumber.js' describe('EVM feature flags', () => { - let dvmAddr: string, evmAddr: string + let dvmAddr: string, evmAddr: string, evmAddrTo: string const container = new MasterNodeRegTestContainer() const client = new ContainerAdapterClient(container) @@ -13,12 +13,12 @@ describe('EVM feature flags', () => { { src: { address: dvmAddr, - amount: '3@DFI', + amount: '5@DFI', domain: TransferDomainType.DVM }, dst: { address: evmAddr, - amount: '3@DFI', + amount: '5@DFI', domain: TransferDomainType.EVM } } @@ -45,12 +45,25 @@ describe('EVM feature flags', () => { return txid } + async function createEvmTx (nonce: number): Promise { + const evmTxHash = await client.evm.evmtx({ + from: evmAddr, + to: evmAddrTo, + value: new BigNumber(0.05), + gasPrice: 23, + gasLimit: 23000, + nonce + }) + return evmTxHash + } + beforeAll(async () => { await container.start() await container.waitForWalletCoinbaseMaturity() dvmAddr = await container.getNewAddress('dfiAddress', 'legacy') evmAddr = await container.getNewAddress('eth', 'eth') + evmAddrTo = await container.getNewAddress('eth', 'eth') await container.call('utxostoaccount', [{ [dvmAddr]: '100@0' }]) await container.generate(1) @@ -88,7 +101,7 @@ describe('EVM feature flags', () => { expect(newEvmAddr).toBeDefined() }) - it.only('should still successfully get eth balance', async () => { + it('should still successfully get eth balance', async () => { const dvmBalances = await client.account.getTokenBalances({}, false) const [dvmBalance] = dvmBalances[0].split('@') const evmBalances = await client.account.getTokenBalances({}, false, { includeEth: true }) @@ -124,6 +137,18 @@ describe('EVM feature flags', () => { expect(typeof txid).toStrictEqual('string') expect(txid.length).toStrictEqual(64) }) + + it('should successfully create a new EVM transaction (EvmTx)', async () => { + // send fund to source evm address + await dvmToEvmTransferDomain() + await container.generate(1) + + const evmTxHash = await createEvmTx(0) + await container.generate(1) + const blockHash: string = await client.blockchain.getBestBlockHash() + const txs = await client.blockchain.getBlock(blockHash, 1) + expect(txs.tx[1]).toStrictEqual(evmTxHash) + }) }) describe('gov attr v0/params/feature/evm is set to false', () => { @@ -146,6 +171,11 @@ describe('EVM feature flags', () => { const promise = evmToDvmTransferDomain() await expect(promise).rejects.toThrow('Cannot create tx, EVM is not enabled') }) + + it('should fail creation of new EVM transaction (EvmTx)', async () => { + const promise = createEvmTx(1) + await expect(promise).rejects.toThrow('Cannot create tx, EVM is not enabled') + }) }) describe('gov attr v0/params/feature/transferdomain is set to false', () => { @@ -168,6 +198,14 @@ describe('EVM feature flags', () => { const promise = evmToDvmTransferDomain() await expect(promise).rejects.toThrow('Cannot create tx, transfer domain is not enabled') }) + + it('should still successfully create new EVM transaction (EvmTx)', async () => { + const evmTxHash = await createEvmTx(1) + await container.generate(1) + const blockHash: string = await client.blockchain.getBestBlockHash() + const txs = await client.blockchain.getBlock(blockHash, 1) + expect(txs.tx[1]).toStrictEqual(evmTxHash) + }) }) describe('gov attr v0/transferdomain/dvm-evm/enabled is set to false', () => { From a4ca2e500ec693902d59a715bb660388395e1cdb Mon Sep 17 00:00:00 2001 From: Lyka Labrada Date: Tue, 8 Aug 2023 14:27:30 +0800 Subject: [PATCH 3/5] update evm feature flag test --- .../__tests__/category/evm/evmFeatureFlag.test.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/jellyfish-api-core/__tests__/category/evm/evmFeatureFlag.test.ts b/packages/jellyfish-api-core/__tests__/category/evm/evmFeatureFlag.test.ts index 1e1569f33..c3d5b07aa 100644 --- a/packages/jellyfish-api-core/__tests__/category/evm/evmFeatureFlag.test.ts +++ b/packages/jellyfish-api-core/__tests__/category/evm/evmFeatureFlag.test.ts @@ -99,16 +99,14 @@ describe('EVM feature flags', () => { it('should still successfully get eth address', async () => { const newEvmAddr = await container.getNewAddress('eth', 'eth') expect(newEvmAddr).toBeDefined() + expect(newEvmAddr).toMatch(/^0x[a-fA-F0-9]{40}$/gm) + expect(newEvmAddr.length).toStrictEqual(42) }) it('should still successfully get eth balance', async () => { - const dvmBalances = await client.account.getTokenBalances({}, false) - const [dvmBalance] = dvmBalances[0].split('@') const evmBalances = await client.account.getTokenBalances({}, false, { includeEth: true }) const [evmBalance] = evmBalances[0].split('@') expect(evmBalance).toBeDefined() - expect(new BigNumber(dvmBalance).minus(new BigNumber(evmBalance))) - .toStrictEqual(new BigNumber(0)) }) }) From b130786ffde9cee4a1636e9ef30e1fe1ace61cb8 Mon Sep 17 00:00:00 2001 From: Lyka Labrada Date: Tue, 8 Aug 2023 14:56:40 +0800 Subject: [PATCH 4/5] update eth balance test --- .../category/evm/evmFeatureFlag.test.ts | 36 +++++++++++++++---- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/packages/jellyfish-api-core/__tests__/category/evm/evmFeatureFlag.test.ts b/packages/jellyfish-api-core/__tests__/category/evm/evmFeatureFlag.test.ts index c3d5b07aa..ded72b253 100644 --- a/packages/jellyfish-api-core/__tests__/category/evm/evmFeatureFlag.test.ts +++ b/packages/jellyfish-api-core/__tests__/category/evm/evmFeatureFlag.test.ts @@ -84,7 +84,7 @@ describe('EVM feature flags', () => { }) describe('all gov attrs for EVM is set to false', () => { - beforeAll(async () => { + it('should still successfully get eth address', async () => { await client.masternode.setGov({ ATTRIBUTES: { 'v0/params/feature/evm': 'false', @@ -94,9 +94,7 @@ describe('EVM feature flags', () => { } }) await container.generate(1) - }) - it('should still successfully get eth address', async () => { const newEvmAddr = await container.getNewAddress('eth', 'eth') expect(newEvmAddr).toBeDefined() expect(newEvmAddr).toMatch(/^0x[a-fA-F0-9]{40}$/gm) @@ -104,9 +102,35 @@ describe('EVM feature flags', () => { }) it('should still successfully get eth balance', async () => { - const evmBalances = await client.account.getTokenBalances({}, false, { includeEth: true }) - const [evmBalance] = evmBalances[0].split('@') - expect(evmBalance).toBeDefined() + await client.masternode.setGov({ + ATTRIBUTES: { + 'v0/params/feature/evm': 'true', + 'v0/params/feature/transferdomain': 'true', + 'v0/transferdomain/dvm-evm/enabled': 'true', + 'v0/transferdomain/evm-dvm/enabled': 'true' + } + }) + await container.generate(1) + await dvmToEvmTransferDomain() + await container.generate(1) + const withoutDvmBalances = await client.account.getTokenBalances({}, false) + const [withoutDvmBalance] = withoutDvmBalances[0].split('@') + + // Disable EVM and try to get ETH balance + await client.masternode.setGov({ + ATTRIBUTES: { + 'v0/params/feature/evm': 'false', + 'v0/params/feature/transferdomain': 'false', + 'v0/transferdomain/dvm-evm/enabled': 'false', + 'v0/transferdomain/evm-dvm/enabled': 'false' + } + }) + await container.generate(1) + const withEvmBalances = await client.account.getTokenBalances({}, false, { includeEth: true }) + const [withEvmBalance] = withEvmBalances[0].split('@') + expect(withEvmBalance).toBeDefined() + expect(new BigNumber(withoutDvmBalance)) + .toStrictEqual(new BigNumber(withEvmBalance).minus(5)) }) }) From 99736ac1650e3be8d3a7069b23e7d85f02300ffe Mon Sep 17 00:00:00 2001 From: Lyka Labrada Date: Thu, 10 Aug 2023 11:20:32 +0800 Subject: [PATCH 5/5] add line spaces --- .../__tests__/category/evm/evmFeatureFlag.test.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/jellyfish-api-core/__tests__/category/evm/evmFeatureFlag.test.ts b/packages/jellyfish-api-core/__tests__/category/evm/evmFeatureFlag.test.ts index ded72b253..3354287b3 100644 --- a/packages/jellyfish-api-core/__tests__/category/evm/evmFeatureFlag.test.ts +++ b/packages/jellyfish-api-core/__tests__/category/evm/evmFeatureFlag.test.ts @@ -111,12 +111,14 @@ describe('EVM feature flags', () => { } }) await container.generate(1) + await dvmToEvmTransferDomain() await container.generate(1) + const withoutDvmBalances = await client.account.getTokenBalances({}, false) const [withoutDvmBalance] = withoutDvmBalances[0].split('@') - // Disable EVM and try to get ETH balance + // disable EVM and try to get ETH balance await client.masternode.setGov({ ATTRIBUTES: { 'v0/params/feature/evm': 'false', @@ -126,6 +128,7 @@ describe('EVM feature flags', () => { } }) await container.generate(1) + const withEvmBalances = await client.account.getTokenBalances({}, false, { includeEth: true }) const [withEvmBalance] = withEvmBalances[0].split('@') expect(withEvmBalance).toBeDefined() @@ -167,6 +170,7 @@ describe('EVM feature flags', () => { const evmTxHash = await createEvmTx(0) await container.generate(1) + const blockHash: string = await client.blockchain.getBestBlockHash() const txs = await client.blockchain.getBlock(blockHash, 1) expect(txs.tx[1]).toStrictEqual(evmTxHash) @@ -224,6 +228,7 @@ describe('EVM feature flags', () => { it('should still successfully create new EVM transaction (EvmTx)', async () => { const evmTxHash = await createEvmTx(1) await container.generate(1) + const blockHash: string = await client.blockchain.getBestBlockHash() const txs = await client.blockchain.getBlock(blockHash, 1) expect(txs.tx[1]).toStrictEqual(evmTxHash)