Skip to content

Commit

Permalink
fix pool balance processing and test
Browse files Browse the repository at this point in the history
  • Loading branch information
ridev6 committed Apr 16, 2024
1 parent f6dea9e commit de5c847
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 20 deletions.
7 changes: 5 additions & 2 deletions ride/voting_emission.ride
Original file line number Diff line number Diff line change
Expand Up @@ -451,13 +451,14 @@ func processPoolBalanceINTERNAL(poolStr: String) = {
# let wxEmission = pool.checkWxEmissionPoolLabel()

let balanceIsOkCurrent = factoryContract.invoke("checkBalance", [lpAssetId], []).exactAs[Boolean]
let balanceIsOkPrevious = !this.getBoolean(pool.keyInsufficientBalances(epochPrevious)).valueOrElse(false)
let balanceIsOkPrevious = !this.getBoolean(pool.keyInsufficientBalances(epochPrevious - 1)).valueOrElse(false)
# check balance, write if balances is ok
# if previous balance and current balance is not ok,
# then set status 3, remove from list, remove wx emission label
let actions = if (!balanceIsOkCurrent) then {
if (!balanceIsOkPrevious) then {
strict deleteWxEmissionInv = factoryContract.invoke("deleteWxEmissionPoolLabel", [amountAssetId, priceAssetId], [])
strict modifyWeightInv = factoryContract.invoke("modifyWeight", [lpAssetId, 0], [])

let poolAddress = getPoolInfo(
amountAssetId,
Expand All @@ -470,7 +471,9 @@ func processPoolBalanceINTERNAL(poolStr: String) = {
DeleteEntry(pool.keyInList())
] ++ poolsListName.deleteNodeActions(pool.poolToString())

listActions
[
IntegerEntry(pool.keyPoolShare(epochPrevious), 0)
] ++ listActions
} else {
[
BooleanEntry(pool.keyInsufficientBalances(epochPrevious), true)
Expand Down
34 changes: 34 additions & 0 deletions test/common_mock/factory_v2.mock.ride
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,26 @@
{-# CONTENT_TYPE DAPP #-}
{-# SCRIPT_TYPE ACCOUNT #-}

let wavesString = "WAVES"

# pool labels
let poolLabelWxEmission = "WX_EMISSION"
let validPoolLabels = [poolLabelWxEmission]

func keyWxEmission(amountAssetId: String, priceAssetId: String)
= "%s%s%s__wxEmission__" + amountAssetId + "__" + priceAssetId

func keyMappingsBaseAsset2internalId(baseAssetStr: String)
= "%s%s%s__mappings__baseAsset2internalId__" + baseAssetStr
func keyMappingPoolAssetsToPoolContractAddress(internalAmountAssetIdStr: Int, internalPriceAssetIdStr: Int)
= "%d%d%s%s__" + internalAmountAssetIdStr.toString() + "__" + internalPriceAssetIdStr.toString() + "__mappings__poolAssets2PoolContract"
func keyMappingPoolContractToLPAsset(poolContractAddress: String)
= "%s%s%s__" + poolContractAddress + "__mappings__poolContract2LpAsset"

func parseAssetId(input: String) = {
if (input == wavesString) then unit else input.fromBase58String()
}

@Callable(i)
func activateNewPool(poolAddress: String, amountAssetStr: String, priceAssetStr: String, lpAssetName: String, lpAssetDescr: String, poolWeight: Int, poolType: String, logo: String) = {
let lpAssetIssueAction = Issue(lpAssetName, lpAssetDescr, 1, 8, true)
Expand All @@ -17,6 +30,27 @@ func activateNewPool(poolAddress: String, amountAssetStr: String, priceAssetStr:
([lpAssetIssueAction], lpAssetIdStr)
}

@Callable(i)
func poolInfoREADONLY(amountAssetIdStr: String, priceAssetIdStr: String) = {
let amountAssetInternalIdOption = this.getInteger(amountAssetIdStr.keyMappingsBaseAsset2internalId())
let priceAssetInternalIdOption = this.getInteger(priceAssetIdStr.keyMappingsBaseAsset2internalId())
let poolContractAddressOption = this.getString(keyMappingPoolAssetsToPoolContractAddress(amountAssetInternalIdOption.value(), priceAssetInternalIdOption.value()))
let lpAssetIdOption = this.getString(poolContractAddressOption.value().keyMappingPoolContractToLPAsset())
let poolExists = amountAssetInternalIdOption.isDefined() && priceAssetInternalIdOption.isDefined() && poolContractAddressOption.isDefined()

let poolInfo = if (poolExists) then {
(
poolContractAddressOption.value().addressFromStringValue(),
lpAssetIdOption.value().parseAssetId()
)
} else unit

([], poolInfo)
}

@Callable(i)
func managePool(poolAddress: String, newStatus: Int) = (nil, unit)

@Callable(i)
func checkWxEmissionPoolLabel(amountAssetId: String, priceAssetId: String) = {
let haveLabel = match keyWxEmission(amountAssetId, priceAssetId).getBoolean() {
Expand Down
2 changes: 1 addition & 1 deletion test/components/voting_emission/_hooks.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const mochaHooks = {
const nonce = random(nonceLength, 'Buffer').toString('hex');
this.votingDuration = 3;
// setup accounts
const contractNames = ['votingEmission', 'votingEmissionCandidate', 'boosting', 'staking', 'factory', 'assetsStore', 'gwxReward', 'votingEmissionRate'];
const contractNames = ['votingEmission', 'votingEmissionCandidate', 'boosting', 'staking', 'factory', 'assetsStore', 'gwxReward', 'votingEmissionRate', 'pool1', 'pool2'];
const userNames = Array.from({ length: 3 }, (_, k) => `user${k}`);
const names = [...contractNames, ...userNames, 'pacemaker'];
this.accounts = Object.fromEntries(names.map((item) => {
Expand Down
81 changes: 64 additions & 17 deletions test/components/voting_emission/finalize_low_balance.spec.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { data } from '@waves/waves-transactions';
import { data, issue } from '@waves/waves-transactions';
import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
import {
Expand All @@ -15,33 +15,58 @@ chai.use(chaiAsPromised);
const { expect } = chai;

describe(`${process.pid}: voting_emission: finalize (low balance)`, () => {
const amountAssetId1 = 'amountAssetId1';
let amountAssetId1;
const amountAssetId1Internal = 0;
const priceAssetId1 = 'priceAssetId1';
let priceAssetId1;
const priceAssetId1Internal = 1;
const amountAssetId2 = 'amountAssetId2';
let amountAssetId2;
const amountAssetId2Internal = 2;
const priceAssetId2 = 'priceAssetId2';
let priceAssetId2;
const priceAssetId2Internal = 3;
const user1GwxAmount = 1000;
const user2GwxAmount = 3000;
const epochLength = 6;
const poolContract1 = 'poolContract1';
const poolContract2 = 'poolContract2';
const poolLpAssetId1 = 'poolLpAssetId1';
const poolLpAssetId2 = 'poolLpAssetId2';
let poolLpAssetId1;
let poolLpAssetId2;
before(async function () {
[
{ id: amountAssetId1 },
{ id: priceAssetId1 },
{ id: amountAssetId2 },
{ id: priceAssetId2 },
{ id: poolLpAssetId1 },
{ id: poolLpAssetId2 },
] = await Promise.all([
broadcastAndWait(issue({
name: 'amountAssetId1', description: '', quantity: 1e6 * 1e8, decimals: 8, reissuable: true, chainId,
}, this.accounts.factory.seed)),
broadcastAndWait(issue({
name: 'priceAssetId1', description: '', quantity: 1e6 * 1e8, decimals: 8, reissuable: true, chainId,
}, this.accounts.factory.seed)),
broadcastAndWait(issue({
name: 'amountAssetId2', description: '', quantity: 1e6 * 1e8, decimals: 8, reissuable: true, chainId,
}, this.accounts.factory.seed)),
broadcastAndWait(issue({
name: 'priceAssetId2', description: '', quantity: 1e6 * 1e8, decimals: 8, reissuable: true, chainId,
}, this.accounts.factory.seed)),
broadcastAndWait(issue({
name: 'poolLpAssetId1', description: '', quantity: 1e6 * 1e8, decimals: 8, reissuable: true, chainId,
}, this.accounts.factory.seed)),
broadcastAndWait(issue({
name: 'poolLpAssetId2', description: '', quantity: 1e6 * 1e8, decimals: 8, reissuable: true, chainId,
}, this.accounts.factory.seed)),
]);
const { addr: dApp, seed } = this.accounts.votingEmission;
await broadcastAndWait(data({
data: [
{ key: `%s%s%s__mappings__baseAsset2internalId__${amountAssetId1}`, type: 'integer', value: amountAssetId1Internal },
{ key: `%s%s%s__mappings__baseAsset2internalId__${priceAssetId1}`, type: 'integer', value: priceAssetId1Internal },
{ key: `%d%d%s%s__${amountAssetId1Internal}__${priceAssetId1Internal}__mappings__poolAssets2PoolContract`, type: 'string', value: poolContract1 },
{ key: `%s%s%s__${poolContract1}__mappings__poolContract2LpAsset`, type: 'string', value: poolLpAssetId1 },
{ key: `%d%d%s%s__${amountAssetId1Internal}__${priceAssetId1Internal}__mappings__poolAssets2PoolContract`, type: 'string', value: this.accounts.pool1.addr },
{ key: `%s%s%s__${this.accounts.pool1.addr}__mappings__poolContract2LpAsset`, type: 'string', value: poolLpAssetId1 },
{ key: `%s%s%s__mappings__baseAsset2internalId__${amountAssetId2}`, type: 'integer', value: amountAssetId2Internal },
{ key: `%s%s%s__mappings__baseAsset2internalId__${priceAssetId2}`, type: 'integer', value: priceAssetId2Internal },
{ key: `%d%d%s%s__${amountAssetId2Internal}__${priceAssetId2Internal}__mappings__poolAssets2PoolContract`, type: 'string', value: poolContract2 },
{ key: `%s%s%s__${poolContract2}__mappings__poolContract2LpAsset`, type: 'string', value: poolLpAssetId2 },
{ key: `%d%d%s%s__${amountAssetId2Internal}__${priceAssetId2Internal}__mappings__poolAssets2PoolContract`, type: 'string', value: this.accounts.pool2.addr },
{ key: `%s%s%s__${this.accounts.pool2.addr}__mappings__poolContract2LpAsset`, type: 'string', value: poolLpAssetId2 },
],
additionalFee: 4e5,
chainId,
Expand Down Expand Up @@ -127,6 +152,7 @@ describe(`${process.pid}: voting_emission: finalize (low balance)`, () => {
});

it('successfull finalize', async function () {
const epoch = 0;
await broadcastAndWait(data({
data: [
{ key: `checkBalanceResult__${poolLpAssetId2}`, type: 'boolean', value: false },
Expand All @@ -135,7 +161,7 @@ describe(`${process.pid}: voting_emission: finalize (low balance)`, () => {
chainId,
}, this.accounts.factory.seed));
const { addr: dApp } = this.accounts.votingEmission;
const { value: startHeight } = await api.addresses.fetchDataKey(dApp, '%s%d__startHeight__0');
const { value: startHeight } = await api.addresses.fetchDataKey(dApp, `%s%d__startHeight__${epoch}`);
await waitForHeight(startHeight + epochLength + 1);
await votingEmission.setMaxDepth({
dApp, caller: this.accounts.votingEmission.seed, value: 20,
Expand All @@ -146,13 +172,34 @@ describe(`${process.pid}: voting_emission: finalize (low balance)`, () => {
const poolWeightMult = 1e8;
const totalVotes = user1GwxAmount + user2GwxAmount;
const pool1Share = (user1GwxAmount / totalVotes) * poolWeightMult;
const pool2Share = (user2GwxAmount / totalVotes) * poolWeightMult;

const dAppState = await api.addresses.data(dApp);
const dAppStateMap = Object.fromEntries(dAppState.map((v) => [v.key, v]));

expect(dAppStateMap['%s__currentEpoch'].value).to.equal(epoch + 1);
expect(dAppStateMap[`%s%s%s%d__poolShare__${amountAssetId1}__${priceAssetId1}__${epoch}`].value).to.equal(pool1Share);
expect(dAppStateMap[`%s%s%s%d__poolShare__${amountAssetId2}__${priceAssetId2}__${epoch}`].value).to.equal(pool2Share);
});

it('pool should be removed from the list', async function () {
const epoch = 1;
const { addr: dApp } = this.accounts.votingEmission;
const { value: startHeight } = await api.addresses.fetchDataKey(dApp, `%s%d__startHeight__${epoch}`);
await waitForHeight(startHeight + epochLength + 1);
await votingEmission.finalize({
dApp, caller: this.accounts.pacemaker.seed,
});
const poolWeightMult = 1e8;
const totalVotes = user1GwxAmount + user2GwxAmount;
const pool1Share = (user1GwxAmount / totalVotes) * poolWeightMult;
const pool2Share = 0;

const dAppState = await api.addresses.data(dApp);
const dAppStateMap = Object.fromEntries(dAppState.map((v) => [v.key, v]));

expect(dAppStateMap['%s__currentEpoch'].value).to.equal(1);
expect(dAppStateMap['%s%s%s%d__poolShare__amountAssetId1__priceAssetId1__0'].value).to.equal(pool1Share);
expect(dAppStateMap['%s%s%s%d__poolShare__amountAssetId2__priceAssetId2__0'].value).to.equal(pool2Share);
expect(dAppStateMap['%s__currentEpoch'].value).to.equal(epoch + 1);
expect(dAppStateMap[`%s%s%s%d__poolShare__${amountAssetId1}__${priceAssetId1}__${epoch}`].value).to.equal(pool1Share);
expect(dAppStateMap[`%s%s%s%d__poolShare__${amountAssetId2}__${priceAssetId2}__${epoch}`].value).to.equal(pool2Share);
});
});

0 comments on commit de5c847

Please sign in to comment.