From 1d57e7468805f6b4cccabe01cb002bcd8504b543 Mon Sep 17 00:00:00 2001 From: TakaYuPP Date: Mon, 6 Jan 2025 17:56:26 +0900 Subject: [PATCH] MERGE PR: feat: added new functions to get the Stats of QVAULT SC (#249) * feat: added new functions to get the Stats of QVAULT SC --- src/contract_core/contract_def.h | 2 +- src/contracts/QVAULT.h | 91 +++++++++++++++++++++++++++++++- test/contract_qvault.cpp | 62 ++++++++++++++++++++++ 3 files changed, 152 insertions(+), 3 deletions(-) diff --git a/src/contract_core/contract_def.h b/src/contract_core/contract_def.h index 9826c336..6d93c39e 100644 --- a/src/contract_core/contract_def.h +++ b/src/contract_core/contract_def.h @@ -213,7 +213,7 @@ constexpr struct ContractDescription {"SWATCH", 123, 10000, sizeof(IPO)}, {"CCF", 127, 10000, sizeof(CCF)}, // proposal in epoch 125, IPO in 126, construction and first use in 127 {"QEARN", 137, 10000, sizeof(QEARN)}, // proposal in epoch 135, IPO in 136, construction in 137 / first donation after END_EPOCH, first round in epoch 138 - {"QVAULT", 138, 10000, sizeof(IPO)}, // proposal in epoch 136, IPO in 137, construction and first use in 138 + {"QVAULT", 138, 10000, sizeof(QVAULT)}, // proposal in epoch 136, IPO in 137, construction and first use in 138 }; constexpr unsigned int contractCount = sizeof(contractDescriptions) / sizeof(contractDescriptions[0]); diff --git a/src/contracts/QVAULT.h b/src/contracts/QVAULT.h index 77e848bd..2745948d 100644 --- a/src/contracts/QVAULT.h +++ b/src/contracts/QVAULT.h @@ -3,7 +3,10 @@ using namespace QPI; constexpr uint64 QVAULT_MAX_REINVEST_AMOUNT = 100000000000ULL; constexpr uint64 QVAULT_QCAP_ASSETNAME = 1346454353; constexpr uint64 QVAULT_QCAP_MAX_SUPPLY = 21000000; +constexpr uint64 QVAULT_INITIAL_EPOCH = 138; +constexpr uint64 QVAULT_QVAULT_MAX_SUPPLY = 676; constexpr uint32 QVAULT_MAX_NUMBER_OF_BANNED_ADDRESSES = 16; +constexpr uint32 QVAULT_MAX_EPOCHS = 4096; struct QVAULT2 { @@ -208,8 +211,53 @@ struct QVAULT : public ContractBase { }; + struct getNumberOfAsset_input + { + uint64 assetName; + id issuer; + uint32 ownershipManagingContractIndex; + }; + + struct getNumberOfAsset_output + { + sint64 numberOfAssetPossessed; + }; + + struct getStatsPerEpoch_input + { + uint32 epoch; + }; + + struct getStatsPerEpoch_output + { + uint64 totalRevenue; + uint64 revenueOfQcapHolders; + uint64 revenueOfOneQcap; + uint64 revenueOfQvaultHolders; + uint64 revenueOfOneQvault; + uint64 revenueOfReinvesting; + uint64 revenueOfDevTeam; + uint64 percentOfReinvested; + uint64 percentOfDistributed; + uint64 percentOfDevTeam; + uint64 percentOfQvaultShareholders; + }; + protected: + struct StatsInfo + { + uint64 totalRevenue; + uint64 revenueOfQcapHolders; + uint64 revenueOfOneQcap; + uint64 revenueOfQvaultHolders; + uint64 revenueOfOneQvault; + uint64 revenueOfReinvesting; + uint64 revenueOfDevTeam; + }; + + array _allEpochStats; + id QCAP_ISSUER; id authAddress1, authAddress2, authAddress3, newAuthAddress1, newAuthAddress2, newAuthAddress3; id reinvestingAddress, newReinvestingAddress1, newReinvestingAddress2, newReinvestingAddress3; @@ -559,9 +607,37 @@ struct QVAULT : public ContractBase _ + PUBLIC_FUNCTION(getNumberOfAsset) + + output.numberOfAssetPossessed = qpi.numberOfPossessedShares(input.assetName, input.issuer, SELF, SELF, input.ownershipManagingContractIndex, input.ownershipManagingContractIndex); + + _ + + PUBLIC_FUNCTION(getStatsPerEpoch) + + if(input.epoch < QVAULT_INITIAL_EPOCH || input.epoch >= QVAULT_MAX_EPOCHS) + { + return ; + } + + output.totalRevenue = state._allEpochStats.get(input.epoch).totalRevenue; + output.revenueOfQcapHolders = state._allEpochStats.get(input.epoch).revenueOfQcapHolders; + output.revenueOfOneQcap = state._allEpochStats.get(input.epoch).revenueOfOneQcap; + output.revenueOfQvaultHolders = state._allEpochStats.get(input.epoch).revenueOfQvaultHolders; + output.revenueOfOneQvault = state._allEpochStats.get(input.epoch).revenueOfOneQvault; + output.revenueOfDevTeam = state._allEpochStats.get(input.epoch).revenueOfDevTeam; + output.revenueOfReinvesting = state._allEpochStats.get(input.epoch).revenueOfReinvesting; + output.percentOfDistributed = QPI::div(output.revenueOfQcapHolders * 100000ULL, output.totalRevenue); + output.percentOfQvaultShareholders = QPI::div(output.revenueOfQvaultHolders * 100000ULL, output.totalRevenue); + output.percentOfDevTeam = QPI::div(output.revenueOfDevTeam * 100000ULL, output.totalRevenue); + output.percentOfReinvested = QPI::div(output.revenueOfReinvesting * 100000ULL, output.totalRevenue); + _ + REGISTER_USER_FUNCTIONS_AND_PROCEDURES REGISTER_USER_FUNCTION(getData, 1); + REGISTER_USER_FUNCTION(getNumberOfAsset, 2); + REGISTER_USER_FUNCTION(getStatsPerEpoch, 3); REGISTER_USER_PROCEDURE(submitAuthAddress, 1); REGISTER_USER_PROCEDURE(changeAuthAddress, 2); @@ -604,6 +680,7 @@ struct QVAULT : public ContractBase struct END_EPOCH_locals { + StatsInfo statsOfEpoch; ::Entity entity; AssetPossessionIterator iter; AssetIssuanceId QCAPId; @@ -635,7 +712,7 @@ struct QVAULT : public ContractBase locals.paymentForReinvest = QVAULT_MAX_REINVEST_AMOUNT; } - qpi.distributeDividends(div(locals.paymentForShareholders, 676ULL)); + qpi.distributeDividends(div(locals.paymentForShareholders, NUMBER_OF_COMPUTORS * 1ULL)); qpi.transfer(state.adminAddress, locals.paymentForDevelopment); qpi.transfer(state.reinvestingAddress, locals.paymentForReinvest); qpi.burn(locals.amountOfBurn); @@ -647,6 +724,16 @@ struct QVAULT : public ContractBase locals.circulatedSupply -= qpi.numberOfPossessedShares(QVAULT_QCAP_ASSETNAME, state.QCAP_ISSUER, state.bannedAddress.get(locals._t), state.bannedAddress.get(locals._t), QX_CONTRACT_INDEX, QX_CONTRACT_INDEX); } + locals.statsOfEpoch.totalRevenue = locals.revenue; + locals.statsOfEpoch.revenueOfQcapHolders = locals.paymentForQCAPHolders; + locals.statsOfEpoch.revenueOfOneQcap = div(locals.paymentForQCAPHolders, locals.circulatedSupply); + locals.statsOfEpoch.revenueOfQvaultHolders = locals.paymentForShareholders; + locals.statsOfEpoch.revenueOfOneQvault = div(locals.paymentForShareholders, NUMBER_OF_COMPUTORS * 1ULL); + locals.statsOfEpoch.revenueOfDevTeam = locals.paymentForDevelopment; + locals.statsOfEpoch.revenueOfReinvesting = locals.paymentForReinvest; + + state._allEpochStats.set(qpi.epoch(), locals.statsOfEpoch); + locals.QCAPId.assetName = QVAULT_QCAP_ASSETNAME; locals.QCAPId.issuer = state.QCAP_ISSUER; @@ -672,4 +759,4 @@ struct QVAULT : public ContractBase } _ -}; \ No newline at end of file +}; diff --git a/test/contract_qvault.cpp b/test/contract_qvault.cpp index 63adb015..74a800be 100644 --- a/test/contract_qvault.cpp +++ b/test/contract_qvault.cpp @@ -249,6 +249,26 @@ class QVAULTChecker : public QVAULT EXPECT_EQ(output.unbannedAddress2, unbannedAddress2); EXPECT_EQ(output.unbannedAddress3, unbannedAddress3); } + + void getNumberOfAssetChecker(const getNumberOfAsset_output& output) + { + EXPECT_EQ(output.numberOfAssetPossessed, QVAULT_QCAP_MAX_SUPPLY); + } + + void getStatsPerEpochChecker(const getStatsPerEpoch_output& output) + { + EXPECT_EQ(output.totalRevenue, _allEpochStats.get(system.epoch).totalRevenue); + EXPECT_EQ(output.revenueOfQcapHolders, _allEpochStats.get(system.epoch).revenueOfQcapHolders); + EXPECT_EQ(output.revenueOfQvaultHolders, _allEpochStats.get(system.epoch).revenueOfQvaultHolders); + EXPECT_EQ(output.revenueOfOneQcap, _allEpochStats.get(system.epoch).revenueOfOneQcap); + EXPECT_EQ(output.revenueOfOneQvault, _allEpochStats.get(system.epoch).revenueOfOneQvault); + EXPECT_EQ(output.revenueOfDevTeam, _allEpochStats.get(system.epoch).revenueOfDevTeam); + EXPECT_EQ(output.revenueOfReinvesting, _allEpochStats.get(system.epoch).revenueOfReinvesting); + EXPECT_EQ(output.percentOfDistributed, QPI::div(_allEpochStats.get(system.epoch).revenueOfQcapHolders * 100000ULL, _allEpochStats.get(system.epoch).totalRevenue)); + EXPECT_EQ(output.percentOfQvaultShareholders, QPI::div(_allEpochStats.get(system.epoch).revenueOfQvaultHolders * 100000ULL, _allEpochStats.get(system.epoch).totalRevenue)); + EXPECT_EQ(output.percentOfReinvested, QPI::div(_allEpochStats.get(system.epoch).revenueOfReinvesting * 100000ULL, _allEpochStats.get(system.epoch).totalRevenue)); + EXPECT_EQ(output.percentOfDevTeam, QPI::div(_allEpochStats.get(system.epoch).revenueOfDevTeam * 100000ULL, _allEpochStats.get(system.epoch).totalRevenue)); + } }; class ContractTestingQvault : protected ContractTesting @@ -289,6 +309,30 @@ class ContractTestingQvault : protected ContractTesting return output; } + QVAULT::getNumberOfAsset_output getNumberOfAsset(uint64 assetName, id issuer, uint32 ownershipManagingContractIndex) const + { + QVAULT::getNumberOfAsset_input input; + QVAULT::getNumberOfAsset_output output; + + input.assetName = assetName; + input.issuer = issuer; + input.ownershipManagingContractIndex = ownershipManagingContractIndex; + + callFunction(QVAULT_CONTRACT_INDEX, 2, input, output); + return output; + } + + QVAULT::getStatsPerEpoch_output getStatsPerEpoch(uint16 epoch) const + { + QVAULT::getStatsPerEpoch_input input; + QVAULT::getStatsPerEpoch_output output; + + input.epoch = epoch; + + callFunction(QVAULT_CONTRACT_INDEX, 3, input, output); + return output; + } + void submitAuthAddress(const id& authAddress, const id& newAuthAddress) { QVAULT::submitAuthAddress_input input; @@ -500,6 +544,8 @@ TEST(ContractQvault, END_EPOCH) uint64 revenue = random(QVAULT_MIN_REVENUE, QVAULT_MAX_REVENUE); increaseEnergy(QVAULT_CONTRACT_ID, revenue); qvault.endEpoch(); + auto output = qvault.getStatsPerEpoch(system.epoch); + qvault.getState()->getStatsPerEpochChecker(output); qvault.getState()->endEpochChecker(revenue, QCAPHolders); } @@ -877,4 +923,20 @@ TEST(ContractQvault, getData) output = qvault.getData(); qvault.getState()->getDataChecker(output); +} + +TEST(ContractQvault, getNumberOfAsset) +{ + ContractTestingQvault qvault; + + id issuer = QVAULT_QCAP_ISSUER; + uint64 assetName = assetNameFromString("QCAP"); + sint64 numberOfShares = QVAULT_QCAP_MAX_SUPPLY; + + increaseEnergy(issuer, QVAULT_ISSUE_ASSET_FEE + QVAULT_TOKEN_TRANSFER_FEE); + EXPECT_EQ(qvault.issueAsset(issuer, assetName, numberOfShares, 0, 0), numberOfShares); + EXPECT_EQ(qvault.TransferShareOwnershipAndPossession(issuer, assetName, numberOfShares, QVAULT_CONTRACT_ID), numberOfShares); + + auto output = qvault.getNumberOfAsset(assetName, issuer, 1); + qvault.getState()->getNumberOfAssetChecker(output); } \ No newline at end of file