From 93fb240149b3a85315192bc488bbd5d93dfb7222 Mon Sep 17 00:00:00 2001 From: Dzmitry Lahoda Date: Tue, 8 Feb 2022 08:39:57 +0200 Subject: [PATCH] test(Runtime Integration Tests): Updated with #560 & #616. BREAKING CHANGE: Types aren't updated yet! Signed-off-by: Dominik Roth Revert "liquidation test and runtime" This reverts commit 825d8242b55602be3b9772165fe416a5d1ca1ccd. Revert "build fix" This reverts commit cf021539d321b3763387ca4d578a6d0989218141. test(Runtime Integration Tests): Fixed type defitions and liquidation strategy test. Signed-off-by: Dominik Roth test(Runtime Integration Tests): Lending Tests W.I.P. Signed-off-by: Dominik Roth test(Runtime Integration Tests): Lending tests W.I.P. Signed-off-by: Dominik Roth test(Runtime Integration Tests): Lending Tests integration W.I.P. & types. Signed-off-by: Dominik Roth test(Runtime Integration Tests): Lending tests integration W.I.P. Market Creation & Types. Signed-off-by: Dominik Roth test(Runtime Integration Tests): Lending tests integration W.I.P. Market Creation & Types. Signed-off-by: Dominik Roth refactor(Lending Pallet): Added lending pallet to runtime. Signed-off-by: Dominik Roth refactor(Lending Pallet): Added lending pallet to runtime W.I.P. Signed-off-by: Dominik Roth test(Runtime Integration Tests): Lending tests integration W.I.P. Vault Setup BREAKING CHANGE: vault.create fails. Signed-off-by: Dominik Roth test(Runtime Integration Tests): Lending tests integration W.I.P. Vault Setup BREAKING CHANGE: vault.create causes a timeout. Signed-off-by: Dominik Roth test(Runtime Integration Tests): Lending tests integration W.I.P. Vault Setup BREAKING CHANGE: vault.create causes a timeout. Signed-off-by: Dominik Roth test(Runtime Integration Tests): Lending tests integration W.I.P. Vault Setup BREAKING CHANGE: vault.create causes a timeout. Signed-off-by: Dominik Roth test(Runtime Integration Tests): Lending tests integration W.I.P. Oracle Setup. Signed-off-by: Dominik Roth test(Runtime Integration Tests): Lending tests integration W.I.P. Boilerplate added. Signed-off-by: Dominik Roth test(Runtime Integration Tests): Lending tests integration W.I.P. Signed-off-by: Dominik Roth build fix Signed-off-by: Dzmitry Lahoda liquidation test and runtime Signed-off-by: Dzmitry Lahoda --- .../test/tests/lending/lendingTests.ts | 192 ++++++++++++++++++ .../createLendingMarketHandler.ts | 32 +++ .../createLiquidationStrategyHandler.ts | 16 ++ .../lending/testHandlers/setupHandler.ts | 44 ++++ .../tests/lending/test_configuration.json | 18 ++ 5 files changed, 302 insertions(+) create mode 100644 integration-tests/runtime-tests/test/tests/lending/lendingTests.ts create mode 100644 integration-tests/runtime-tests/test/tests/lending/testHandlers/createLendingMarketHandler.ts create mode 100644 integration-tests/runtime-tests/test/tests/lending/testHandlers/createLiquidationStrategyHandler.ts create mode 100644 integration-tests/runtime-tests/test/tests/lending/testHandlers/setupHandler.ts create mode 100644 integration-tests/runtime-tests/test/tests/lending/test_configuration.json diff --git a/integration-tests/runtime-tests/test/tests/lending/lendingTests.ts b/integration-tests/runtime-tests/test/tests/lending/lendingTests.ts new file mode 100644 index 00000000000..0bbcbabc2b5 --- /dev/null +++ b/integration-tests/runtime-tests/test/tests/lending/lendingTests.ts @@ -0,0 +1,192 @@ +/** + * Tests for the lending pallet. + * + * Before tests, we need to create an oracle, and fake some data. + * Then we need to create a lending pool to test. + * + */ +import {KeyringPair} from "@polkadot/keyring/types"; +import {txOracleAddAssetAndInfoSuccessTest} from "@composabletests/tests/oracle/testHandlers/addAssetAndInfoTests"; +import {expect} from "chai"; +import { + handleLendingAssetMintSetup, + handleLendingVaultSetup +} from "@composabletests/tests/lending/testHandlers/setupHandler"; +import {sendAndWaitForSuccess, waitForBlocks} from "@composable/utils/polkadotjs"; +import testConfiguration from './test_configuration.json'; +import {createLendingMarketHandler} from "@composabletests/tests/lending/testHandlers/createLendingMarketHandler"; +import { + createLiquidationStrategyHandler +} from "@composabletests/tests/lending/testHandlers/createLiquidationStrategyHandler"; +import {txOracleSubmitPriceSuccessTest} from "@composabletests/tests/oracle/testHandlers/submitPriceTests"; +import { + runBeforeTxOracleSetSigner, + txOracleSetSignerSuccessTest +} from "@composabletests/tests/oracle/testHandlers/setSignerTests"; + +describe('Lending Tests', function() { + if (!testConfiguration.enabled) + return; + let oracleId:number, lendingAssetId:number; + let sudoKey:KeyringPair, + lenderWallet:KeyringPair, + oracleControllerWallet:KeyringPair, + oracleSignerWallet:KeyringPair, + vaultManagerWallet:KeyringPair; + + before('Before Lending Tests: Base Setup', async function() { + if (!testConfiguration.enabledTests.runBeforeBaseSetup) + return; + lendingAssetId = 42000; + sudoKey = walletAlice; + oracleControllerWallet = walletAlice; + vaultManagerWallet = walletAlice; + lenderWallet = walletAlice.derive('/lenderWallet'); + oracleSignerWallet = walletAlice.derive('/oracleSigner'); + }) + + before('Before Lending Tests: Mint lending asset', async function() { + if (!testConfiguration.enabledTests.runBeforeMintLendingAsset) + return; + // Timeout set to 2 minutes. + this.timeout(2 * 60 * 1000) + const mintingAmount = 1000000000000 + const result = await handleLendingAssetMintSetup(sudoKey, lendingAssetId, lenderWallet, mintingAmount); + expect(result[0].isOk).to.be.true; + expect(result[1].isOk).to.be.true; + }); + + before ('Before Lending Tests: Create asset vault', async function() { + if (!testConfiguration.enabledTests.runBeforeCreateAssetVault) + return; + // Timeout set to 2 minutes. + this.timeout(2 * 60 * 1000); + await waitForBlocks(); + const reserved = api.createType('Perquintill', 1000000000000); + const strategyMap = new Map(); + strategyMap.set('AccountId32', api.createType('AccountId32', vaultManagerWallet.address)); + strategyMap.set('Perquintill', api.createType('Perquintill', 1000000000000)); + const strategy = api.createType('BTreeMap', strategyMap); + const depositAmount = api.createType('u128', 1000000000000); + const result = await handleLendingVaultSetup(lendingAssetId, reserved, vaultManagerWallet, strategy, depositAmount); + console.debug(result.toString()); + }); + + before('Before Lending Tests: Create Oracle', async function() { + if (!testConfiguration.enabledTests.runBeforeCreateOracle) + return; + // Timeout set to 4 minutes. + this.timeout(4 * 60 * 1000); + // Create oracle + const assetId = api.createType('u128', lendingAssetId); + const threshold = api.createType('Percent', 50); + const minAnswers = api.createType('u32', 2); + const maxAnswers = api.createType('u32', 5); + const blockInterval = api.createType('u32', 6); + const reward = api.createType('u128', 150000000000); + const slash = api.createType('u128', 100000000000); + const {data: [result],} = await txOracleAddAssetAndInfoSuccessTest( + oracleControllerWallet, + assetId, + threshold, + minAnswers, + maxAnswers, + blockInterval, + reward, + slash + ); + if (result.isErr) + console.debug(result.asErr.toString()); + expect(result.isOk).to.be.true; + oracleId = (await api.query.oracle.assetsCount()).toNumber(); + }); + + before('Setting oracle signer', async function() { + if (!testConfiguration.enabledTests.runBeforeSetOracleSigner) + this.skip(); + // Setting timeout to 2 minutes. + this.timeout(2 * 60 * 1000); + const sudoKey = walletAlice; + const {data: [result],} = await runBeforeTxOracleSetSigner(sudoKey, oracleSignerWallet); // Making sure we have funds. + expect(result.isOk).to.be.true; + const {data: [resultAccount0, resultAccount1],} = await txOracleSetSignerSuccessTest(oracleControllerWallet, oracleSignerWallet) + .catch(function(exc) { return {data:[exc]}; /* We can't call this.skip() from here. */ }); + if (resultAccount0.message == "oracle.SignerUsed: This signer is already in use" || + resultAccount0.message == "oracle.ControllerUsed: This controller is already in use") + return this.skip(); // If the test is run a second time on the same chain, we already have a signer set. + expect(resultAccount0).to.not.be.an('Error'); + expect(resultAccount1).to.not.be.an('Error'); + expect(resultAccount0.toString()).to.be.equal(api.createType('AccountId32', oracleSignerWallet.publicKey).toString()); + expect(resultAccount1.toString()).to.be.equal(api.createType('AccountId32', oracleControllerWallet.publicKey).toString()); + }); + + before('Submit new price to oracle', async function() { + if (!testConfiguration.enabledTests.runBeforeSubmitPriceOracle) + this.skip(); + // Setting timeout to 2 minutes. + this.timeout(2 * 60 * 1000); + const price = api.createType('u128', 10000); + const assetId = api.createType('u128', lendingAssetId); + const {data: [result],} = await txOracleSubmitPriceSuccessTest(oracleSignerWallet, price, assetId); + expect(result).to.not.be.an('Error'); + expect(result.toString()).to.be + .equal(api.createType('AccountId32', oracleSignerWallet.publicKey).toString()); + }); + + describe('Liquidation Strategy Success Tests', function() { + it('Can create liquidation strategy (DutchAuction, LinearDecrease)', async function() { + if (!testConfiguration.enabledTests.canCreateLiquidationStrategy.createLiquidationStrategyDutchAuctionLinearDecrease) + this.skip(); + // Setting timeout to 2 minutes. + this.timeout(2 * 60 * 1000); + const configuration = api.createType('PalletLiquidationsLiquidationStrategyConfiguration', { + DutchAuction: api.createType('ComposableTraitsTimeTimeReleaseFunction', { + LinearDecrease: api.createType('ComposableTraitsTimeLinearDecrease', { + total: api.createType('u64', 1) + }) + }), + UniswapV2: "Null", + XcmDex: "Null" + }); + const { data: [result],} = await createLiquidationStrategyHandler(sudoKey, configuration); + console.debug(result); + }); + }); + + describe('Lending Market Creation Success Tests', function () { + it('Can create lending market (Jump Interest Rate Model', ()=>{return}); + + it('Can create lending market (Curve Interest Rate Model)', async function () { + if (!testConfiguration.enabledTests.canCreateLendingMarket.createMarketCurveInterestRateModel) + this.skip(); + // Setting timeout to 2 minutes. + this.timeout(2 * 60 * 1000); + const collateralFactor = BigInt(2000000000000000000); + const underCollaterializedWarnPercent = api.createType('Percent', 10); + const liquidators = api.createType('Vec', []); + const mathCurveModel = api.createType('ComposableTraitsLendingMathCurveModel', { + baseRate: api.createType('u128', 100000000000) + }); + const interestRateModel = api.createType('ComposableTraitsLendingMathInterestRateModel', { + curve: mathCurveModel + }); + const currencyPair = api.createType('ComposableTraitsDefiCurrencyPair', { + base: api.createType('u128', 1), // Collateral Asset + quote: api.createType('u128', lendingAssetId) // Borrow Asset + }); + const reservedFactor = api.createType('Perquintill', 1); + const {data: [result],} = await createLendingMarketHandler(vaultManagerWallet, collateralFactor, underCollaterializedWarnPercent, liquidators, interestRateModel, currencyPair, reservedFactor) + console.debug(result.toString()); + }); + + it('Can create lending market (DynamicPIDController Interest Rate Model', ()=>{return}); + + it('Can create lending market (Double Exponent Interest Rate Model', ()=>{return}); + }); + + describe('Borrow success tests', function() { + it('Lending Tests: Borrow very high amounts => High Interest Rate => High Borrow Rate', ()=>{return true}); // ToDo (D. Roth): Implement. + + it('Lending Tests: Very low borrow amount => Low accrue', ()=>{return true}); // ToDo (D. Roth): Implement. + }); +}); diff --git a/integration-tests/runtime-tests/test/tests/lending/testHandlers/createLendingMarketHandler.ts b/integration-tests/runtime-tests/test/tests/lending/testHandlers/createLendingMarketHandler.ts new file mode 100644 index 00000000000..d6cb7a67502 --- /dev/null +++ b/integration-tests/runtime-tests/test/tests/lending/testHandlers/createLendingMarketHandler.ts @@ -0,0 +1,32 @@ +import {sendAndWaitForSuccess} from "@composable/utils/polkadotjs"; + + +export async function createLendingMarketHandler( + wallet, + collateralFactor, + underCollaterializedWarnPercent, + liquidators, + interestRateModel, + currencyPair, + reservedFactor +) { + const input = api.createType('ComposableSupportValidationValidated', { + value: api.createType('ComposableTraitsLendingCreateInput', { + updatable: api.createType('ComposableTraitsLendingUpdateInput', { + collateralFactor: collateralFactor, + underCollaterializedWarnPercent: underCollaterializedWarnPercent, + liquidators: liquidators, + interestRateModel: interestRateModel, + }), + currencyPair: currencyPair + }), + reservedFactor: reservedFactor + }); + + return await sendAndWaitForSuccess( + api, + wallet, + api.events.lending.MarketCreated.is, + api.tx.lending.createMarket(input) + ); +} \ No newline at end of file diff --git a/integration-tests/runtime-tests/test/tests/lending/testHandlers/createLiquidationStrategyHandler.ts b/integration-tests/runtime-tests/test/tests/lending/testHandlers/createLiquidationStrategyHandler.ts new file mode 100644 index 00000000000..a30ea672d6e --- /dev/null +++ b/integration-tests/runtime-tests/test/tests/lending/testHandlers/createLiquidationStrategyHandler.ts @@ -0,0 +1,16 @@ +import {sendAndWaitForSuccess} from "@composable/utils/polkadotjs"; + + +export async function createLiquidationStrategyHandler( + sudoKey, + configuration +) { + return await sendAndWaitForSuccess( + api, + sudoKey, + api.events.sudo.Sudid.is, + api.tx.sudo.sudo( + api.tx.liquidations.addLiqudationStrategy(configuration) + ) + ); +} \ No newline at end of file diff --git a/integration-tests/runtime-tests/test/tests/lending/testHandlers/setupHandler.ts b/integration-tests/runtime-tests/test/tests/lending/testHandlers/setupHandler.ts new file mode 100644 index 00000000000..ee47f5ddabb --- /dev/null +++ b/integration-tests/runtime-tests/test/tests/lending/testHandlers/setupHandler.ts @@ -0,0 +1,44 @@ +import {sendAndWaitForSuccess, waitForBlocks} from "@composable/utils/polkadotjs"; + + +export async function handleLendingAssetMintSetup(sudoKey, assetId, lendingWallet, mintingAmount) { + const {data: [result1],} = await sendAndWaitForSuccess( + api, + sudoKey, + api.events.sudo.Sudid.is, + api.tx.sudo.sudo( + api.tx.assets.mintInto(assetId, lendingWallet.publicKey, mintingAmount) + ) + ); + await waitForBlocks(); // Let's wait a block, cause we sometimes failed here otherwise. + const {data: [result2],} = await sendAndWaitForSuccess( + api, + sudoKey, + api.events.sudo.Sudid.is, + api.tx.sudo.sudo( + api.tx.assets.mintInto(1, lendingWallet.publicKey, mintingAmount) + ) + ); + return [result1, result2]; +} + +export async function handleLendingVaultSetup( + vaultAssetId, + reserved, + vaultManagerWallet, + strategies, + depositAmount +) { + const vault = api.createType('ComposableTraitsVaultVaultConfig', { + assetId: api.createType('u128', vaultAssetId), + reserved: api.createType('Perquintill', reserved), + manager: api.createType('AccountId32', vaultManagerWallet.publicKey), + strategies: strategies//api.createType('(AccountId32, Perquintill)', strategies) + }); + return await sendAndWaitForSuccess( + api, + vaultManagerWallet, + api.events.vault.VaultCreated.is, + api.tx.vault.create(vault, depositAmount) + ); +} diff --git a/integration-tests/runtime-tests/test/tests/lending/test_configuration.json b/integration-tests/runtime-tests/test/tests/lending/test_configuration.json new file mode 100644 index 00000000000..1d3492c063d --- /dev/null +++ b/integration-tests/runtime-tests/test/tests/lending/test_configuration.json @@ -0,0 +1,18 @@ +{ + "enabled": true, + "enabledTests": { + "runBeforeBaseSetup": true, + "runBeforeMintLendingAsset": true, + "runBeforeCreateAssetVault": false, + "runBeforeCreateOracle": true, + "runBeforeSetOracleSigner": true, + "runBeforeSubmitPriceOracle": true, + "canCreateLiquidationStrategy": { + "createLiquidationStrategyDutchAuctionLinearDecrease": true + }, + "canCreateLendingMarket": { + "createMarketJumpInterestRateModel": true, + "createMarketCurveInterestRateModel": true + } + } +} \ No newline at end of file